spoj705( 求不相同的子串个数)

2024-09-09 17:18
文章标签 相同 个数 子串 spoj705

本文主要是介绍spoj705( 求不相同的子串个数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题意:求串s的不同子串的个数

解题思路:任何子串都是某个后缀的前缀,对n个后缀排序,求某个后缀的前缀的个数,减去height[i](第i个后缀与第i-1 个后缀有相同的height[i]个前缀)。

代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<string>
#include<vector>
#define N 50005
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 10e-6using namespace std;
char s[N];
int r[N],wa[N],wb[N],wv[N],WS[N],sa[N];
bool cmp(int *r,int a,int b,int l)
{return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int n,int m)
{int i, j, p, *x = wa, *y = wb, *t;for(i = 0; i < m; i++)  WS[i] = 0;for(i = 0; i < n; i++)  WS[ x[i] = r[i] ]++;for(i = 1; i < m; i++)  WS[i] += WS[i-1];for(i = n-1; i >= 0; i--)   sa[ --WS[ x[i] ] ] = i;for(j = 1,p = 1; p < n; j*=2, m = p){for(p = 0,i = n-j; i < n; i++)  y[p++] = i;for(i = 0; i < n; i++)  if(sa[i] >= j)  y[p++] = sa[i] - j;for(i = 0; i < n; i++)  wv[i] = x[ y[i] ];for(i = 0; i < m; i++)  WS[i] = 0;for(i = 0; i < n; i++)  WS[ wv[i] ]++;for(i = 1; i < m; i++)  WS[i] += WS[i-1];for(i = n-1; i >= 0; i--)   sa[ --WS[ wv[i] ] ] = y[i];for(t = x,x = y,y = t,p = 1,x[ sa[0] ] = 0, i = 1; i < n; i++)x[ sa[i] ] = cmp(y,sa[i-1],sa[i],j) ? p-1 : p++;}
}
int rank[N],height[N];
void calheight(int n)
{int i,j,k = 0;for(i = 1; i <= n; i++) rank[ sa[i] ] = i;for(i = 0; i < n; height[ rank[i++] ] = k)for(k ? k-- : 0, j = sa[ rank[i] - 1 ]; r[i+k] == r[j+k]; k++);
}
void solve(int n)
{int ans = 0;int i;//  for(i = 1; i <= n; i++) cout<<sa[i]<<" ";cout<<endl;
//    for(i = 1; i <= n; i++) cout<<height[i]<<" ";cout<<endl;for(int i = 1; i <= n; i++)ans += (n-sa[i]-height[i]);printf("%d\n",ans);
}
int main()
{int t;scanf("%d",&t);while(t--){int i;scanf("%s",s);int n = strlen(s);for(i = 0; i < n; i++)r[i] = s[i]+1;r[n] = 0;da(n+1,130);calheight(n);//    for(i = 0; i <= n; i++)//      cout<<height[i]<<" ";// cout<<endl;solve(n);}return 0;
}


这篇关于spoj705( 求不相同的子串个数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1151785

相关文章

poj2406(连续重复子串)

题意:判断串s是不是str^n,求str的最大长度。 解题思路:kmp可解,后缀数组的倍增算法超时。next[i]表示在第i位匹配失败后,自动跳转到next[i],所以1到next[n]这个串 等于 n-next[n]+1到n这个串。 代码如下; #include<iostream>#include<algorithm>#include<stdio.h>#include<math.

poj3261(可重复k次的最长子串)

题意:可重复k次的最长子串 解题思路:求所有区间[x,x+k-1]中的最小值的最大值。求sa时间复杂度Nlog(N),求最值时间复杂度N*N,但实际复杂度很低。题目数据也比较水,不然估计过不了。 代码入下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring

XTU 1233 n个硬币连续m个正面个数(dp)

题面: Coins Problem Description: Duoxida buys a bottle of MaiDong from a vending machine and the machine give her n coins back. She places them in a line randomly showing head face or tail face o

O(n)时间内对[0..n^-1]之间的n个数排序

题目 如何在O(n)时间内,对0到n^2-1之间的n个整数进行排序 思路 把整数转换为n进制再排序,每个数有两位,每位的取值范围是[0..n-1],再进行基数排序 代码 #include <iostream>#include <cmath>using namespace std;int n, radix, length_A, digit = 2;void Print(int *A,

PHP最长单一子串

<?php//方法一$s='abcccddddddcdefg';$max='';while($s!=''){$i=0; while($i<strlen($s) && $s[$i]==$s[0]) $i++;if ($i>strlen($max)){$max=substr($s,0,$i);} $s=substr($s,$i);}echo $m

如何根据相同分隔符提取间隔数据?

最近遇到很多提问怎么提取字符的,而这些问题都有一个相同的特征,就是要提取的内容与内容之间,都有着相同的分隔符。当然,这种问题直接用“数据” →  “分列”功能就可以一步到位实现的,但有人喜欢折腾,而更多的人又非得指定函数公式的方法,或者更多的是要保持数据的同步性。   下面,我们就来讲讲用函数公式应该怎么实现这个提取,首先来个数据和要求,如下图,将 - 号间隔的内容依次提取到右边单元格内:

eclipse中相同变量显示变色设置

java文件的设置"Window"-"preferences"-"Java"-"Editor"-"Mark Occurrences"复选框勾选 js文件的设  置"Window"-"preferences"-"web"-"javascript"-"Mark Occurrences"复选框勾选 。

MyBatis学习——解决字段名与实体类属性名不相同的冲突

转载地址:http://www.cnblogs.com/xdp-gacl/p/4264425.html

LCP 485. 最大连续 1 的个数[lleetcode -11]

从今天起,我们的算法开始研究搜索,首先就是DFS深度优先搜索(depth-first seach,DFS)在搜索到一个新的节点时,立即对该新节点进行遍 历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现。对于树结构而言, 由于总是对新节点调用遍历,因此看起来是向着“深”的方向前进。 下面是一个一维的DFS算法 LCP 485. 最大连续 1 的个数 给定一个二进制数组 nu

【UVA】10066-The Twin Towers(最长公共子串问题)

赤裸裸的最长公共子串问题,没什么好说的,注意的是,每组数据后面都有一个空行。 13996019 10066 The Twin Towers Accepted C++ 0.015 2014-08-06 00:34:53 #include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using