【kmp】【后缀数组】【连续重复子串】Power Strings POJ2406
来源:互联网 发布:Windows网络适配器命令 编辑:程序博客网 时间:2024/05/15 06:36
Power Strings
Description
Input
Output
Sample Input
abcdaaaaababab.
Sample Output
143
Hint
Source
先说说后缀数组,比如ababab
我们枚举重复串的长度len
比如len=2
如果说此时满足要求,那么后缀 0 和 后缀 2 的公共部分必定有 n - len 的长度
后缀 0 :ababab
后缀 2 :abab
所以穷举 len 即可
复杂度O(N),然后后缀数组O(NlogN) + O(N)
一交poj,超时了。。。。。
后来看了网上题解才发现后缀数组确实要超时。。。都是用kmp写的
(以下转自别人博客)
对于数组s[0~n-1],计算next[0~n](多计算一位)。
考虑next[n],假设t=n-next[n],如果n%t==0,则t就是问题的解,否则解为1。
这样考虑:
比如字符串"abababab",
a b a b a b a b *
next -1 0 1 2 3 4 5 6 7
考虑这样的模式匹配,将"abababab#"当做主串,"abababab*"当做模式串,于是进行匹配到n(n=8)时,出现了不匹配:
主串 abababab#
模式串 abababab*
于是模式串需要回溯到next[*]=7,这之前的主串和模式串对应相等,于是需要模式串向右滚动的位移是d=n-next[n]=2,即:
123456789
主串 abababab#
模式串 abababab*
于是可以看出,s[0~1]=s[3~4]=s[5~6]=s[7~8]。
所以位移d=n-next[n]可以看作是构成字符串s的字串(如果n%d==0,存在这样的构成),相应的重复次数也就是n/d。
这样O(N)就可以了
测评情况(POJ)(超时的是后缀数组)
C++ AC Code(kmp)
/*http://blog.csdn.net/jiangzh7By Jiangzh*/#include<cstdio>#include<cstring>char s[1000000+10];int len;int next[1000000+10];void getnext(){memset(next,0,sizeof(next));next[0]=-1;int j=0,k=-1;while(j<len){if(k==-1||s[j]==s[k]) next[++j]=++k;else k=next[k];}}int main(){freopen("poj2406.in","r",stdin);freopen("2406kmp.out","w",stdout);while(1){memset(s,0,sizeof(s));scanf("%s",s);len=strlen(s);if(!strcmp(s,".")) break;getnext();//for(int i=0;i<=len;i++) printf("%d ",next[i]);puts("");if(len!=next[len] && len%(len-next[len])==0) printf("%d\n",len/(len-next[len]));else printf("1\n");}return 0;}
C++ TLE Code(Suffix Array)
/*http://blog.csdn.net/jiangzh7By Jiangzh*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=1000000+10;char s[N];int rank[N],sa[N];int c[N],tmp[N];int height[N];int lcp[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=rank,*y=tmp;memset(c,0,sizeof(c));for(i=0;i<n;i++) c[ x[i]=s[i] ]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[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;memset(c,0,sizeof(c));for(i=0;i<n;i++) c[x[y[i]]]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y); x[sa[0]]=0;for(p=1,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;}for(i=0;i<n;i++) rank[sa[i]]=i;int k=0;for(i=0;i<n;height[x[i++]]=k)for(k?k--:0,j=sa[x[i]-1];s[i+k]==s[j+k];k++);}void work(){int n=strlen(s);s[n++]='$';DA(n,'z'+1);/*for(int i=0;i<n;i++){printf("%d %d ",sa[i],height[i]);puts(s+sa[i]);}*/lcp[rank[0]]=0x3f3f3f3f;for(int i=rank[0]-1;i>0;i--) lcp[i]=min(lcp[i+1],height[i+1]);for(int i=rank[0]+1;i<n;i++) lcp[i]=min(lcp[i-1],height[i]);//for(int i=0;i<n;i++) printf("%d ",lcp[i]);puts("");for(int len=1;len<n;len++)if((n-1)%len==0){if(lcp[rank[len]]==(n-1)-len){printf("%d\n",(n-1)/len);break;}}}int main(){freopen("poj2406.in","r",stdin);freopen("poj2406.out","w",stdout);while(1){memset(sa,0,sizeof(sa));memset(rank,0,sizeof(rank));memset(c,0,sizeof(c));memset(tmp,0,sizeof(tmp));memset(s,0,sizeof(s));scanf("%s",s);if(!strcmp(s,".")) break;work();}return 0;}
- 【kmp】【后缀数组】【连续重复子串】Power Strings POJ2406
- poj 2406 Power Strings 【KMP求最小循环节】【后缀数组求连续重复子串】
- POJ 2406 Power Strings(后缀数组[连续重复子串])
- [KMP][后缀数组] poj2406 Power Strings
- POJ2406 Power Strings 【KMP 或 后缀数组】
- poj2406 Power Strings(最大重复子串)
- POJ2406:Power Strings(后缀数组DC3)
- poj2406 Power Strings 后缀数组 DC3算法
- 【KMP】 poj2406 Power Strings
- poj2406 Power Strings-------KMP
- [POJ2406] Power Strings[KMP]
- poj2406 Power Strings kmp
- POJ2406 Power Strings 【KMP】
- poj2406 Power Strings (KMP)
- poj2406-Power Strings(kmp)
- poj2406 Power Strings(KMP)
- POJ2406 Power Strings【KMP】
- poj2406 power strings 【KMP】
- 文件系统ext3的文件大小限制
- 进程通信方式
- malloc,calloc,realloc等内存分配函数区别
- eclipse 配置el解析规则
- void Uart_Printf(char *fmt,...)
- 【kmp】【后缀数组】【连续重复子串】Power Strings POJ2406
- Java中的split()
- 在WIN7环境下装的SNORT+BASE构建IDS环境 出现问题,在线急等
- Tomcat连接线程池配置
- 决定把相关文章迁移到这上面。。
- 使用json格式最为数据传输的格式,代码混淆后数据没有上传成功
- POJO 与javaBean(普通bean和EJB)
- 深入浅出Symfony2 - 如何提高网站响应速度
- android客户端程序和网页浏览的程序的区别