这题可以用后缀数组,KMP方法做

后缀数组做法开始想不出来,看的题解,方法是枚举串长len的约数k,看lcp(suffix(0), suffix(k))的长度是否为n- k ,若为真则len / k即为结果。

若lcp(suffix(0), suffix(k))的长度为n- k,则将串每k位分成一段,则第1段与第2段可匹配,又可推得第2段与第3段可匹配……一直递归下去,可知每k位都是相同的,画图可看出匹配过程类似于蛇形。

用倍增算法超时,用dc3算法2.5秒勉强过。

#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 1000108
int sa[maxn * 3];//r[]和sa[]数组要开三倍大小
int LCP[maxn]; #define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
#define min(a, b) (a < b?a : b)
int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
int c0(int *r,int a,int b)
{return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2];}
int c12(int k,int *r,int a,int b)
{if(k==2) return r[a]<r[b]||r[a]==r[b]&&c12(1,r,a+1,b+1);
else return r[a]<r[b]||r[a]==r[b]&&wv[a+1]<wv[b+1];}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i=0;i<n;i++) wv[i]=r[a[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--) b[--ws[wv[i]]]=a[i];
return;
}
void dc3(int *r,int *sa,int n,int m)
{
int i,j,*rn=r+n,*san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p;
r[n]=r[n+1]=0;
for(i=0;i<n;i++) if(i%3!=0) wa[tbc++]=i;
sort(r+2,wa,wb,tbc,m);
sort(r+1,wb,wa,tbc,m);
sort(r,wa,wb,tbc,m);
for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++)
rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++;
if(p<tbc) dc3(rn,san,tbc,p);
else for(i=0;i<tbc;i++) san[rn[i]]=i;
for(i=0;i<tbc;i++) if(san[i]<tb) wb[ta++]=san[i]*3;
if(n%3==1) wb[ta++]=n-1;
sort(r,wb,wa,ta,m);
for(i=0;i<tbc;i++) wv[wb[i]=G(san[i])]=i;
for(i=0,j=0,p=0;i<ta && j<tbc;p++)
sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++];
for(;i<ta;p++) sa[p]=wa[i++];
for(;j<tbc;p++) sa[p]=wb[j++];
return;
}
int rank[maxn],height[maxn];
void calheight(int *r,int *sa,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++);
return;
} char str[maxn];
int r[maxn * 3]; int hs[1000];
int main(){
while(~scanf("%s", str) && str[0] != '.'){
int len = 0;
int i;
memset(hs, 0, sizeof(hs));
int cnt = 0;
for(i = 0; str[i]; i++){
if(hs[str[i]] == 0){
hs[str[i]] = ++cnt;
}
r[i] = hs[str[i]];
}
len = i;
r[len] = 0; dc3(r, sa, len + 1, cnt + 1);
calheight(r, sa, len);
LCP[rank[0] ] = len;
for(int i = rank[0] + 1; i <= len; i++){
LCP[i] = min(LCP[i - 1], height[i]);
} for(int i = rank[0] - 1; i >= 1; i--){
LCP[i] = min(LCP[i + 1], height[i + 1]);
} int ans = len;
for(int i = 1; i <= len / 2; i++){
if(len % i == 0){
if(LCP[rank[i]] == len - i){
ans = i;
break;
}
}
}
printf("%d\n", len / ans);
}
return 0;
}

之后顿悟出KMP的做法,原理与上类似,但效率高好多,100多毫秒过。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
const int N = 1000008, INF = 0x3F3F3F3F;
#define MS(a, num) memset(a, num, sizeof(a))
#define PB(A) push_back(A)
#define FOR(i, n) for(int i = 0; i < n; i++)
char str[N];
int f[N];
void getF(char P[]){
f[0]=-1;
int i = 0, j = -1;
while(P[i]){
if(j == -1 ||P[i]==P[j]) {
i++; j++;
f[i] = j;
}else{
j=f[j];
}
}
}
int main(){
while(~scanf("%s", str) && str[0] != '.'){
getF(str);
int len = strlen(str);
int a = len - 1;
int b = f[a];
if(a && str[a] == str[b] && len % (a - b) == 0){
printf("%d\n", len / (a - b));
}else{
printf("1\n");
} }
return 0;
}

  

POJ2406 Power Strings(KMP,后缀数组)的更多相关文章

  1. POJ2406 Power Strings —— KMP or 后缀数组 最小循环节

    题目链接:https://vjudge.net/problem/POJ-2406 Power Strings Time Limit: 3000MS   Memory Limit: 65536K Tot ...

  2. poj2406 Power Strings (kmp 求最小循环字串)

    Power Strings   Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 47748   Accepted: 19902 ...

  3. POJ - 2406 Power Strings (后缀数组DC3版)

    题意:求最小循环节循环的次数. 题解:这个题其实可以直接用kmp去求最小循环节,然后在用总长度除以循环节.但是因为在练后缀数组,所以写的后缀数组版本.用倍增法会超时!!所以改用DC3法.对后缀数组还不 ...

  4. POJ2406 Power Strings(KMP)

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 56162   Accepted: 23370 Description Giv ...

  5. POJ2406 Power Strings KMP算法

    给你一个串s,如果能找到一个子串a,连接n次变成它,就把这个串称为power string,即a^n=s,求最大的n. 用KMP来想,如果存在的话,那么我每次f[i]的时候退的步数应该是一样多的  譬 ...

  6. poj2406 Power Strings(kmp)

    poj2406 Power Strings(kmp) 给出一个字符串,问这个字符串是一个字符串重复几次.要求最大化重复次数. 若当前字符串为S,用kmp匹配'\0'+S和S即可. #include & ...

  7. POJ2406 Power Strings 【KMP 或 后缀数组】

    电源串 时间限制: 3000MS   内存限制: 65536K 提交总数: 53037   接受: 22108 描述 给定两个字符串a和b,我们定义a * b是它们的连接.例如,如果a =" ...

  8. poj 2406 Power Strings (kmp 中 next 数组的应用||后缀数组)

    http://poj.org/problem?id=2406 Power Strings Time Limit: 3000MS   Memory Limit: 65536K Total Submiss ...

  9. POJ2406Power Strings (最小循环节)(KMP||后缀数组)

    Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc&quo ...

随机推荐

  1. Ubuntu固定ip和dns配置和查看

    1.查看dns: cat /etc/resolv.conf 2.Ubuntu固定ip sudo vim /etc/network/interfaces 修改如下部分: auto p3p1 iface ...

  2. 详解 Too many open files

    运行在Linux系统上的Java程序可能会出现"Too many open files"的异常情况,且常见于高并发访问文件系统,多线程网络连接等场景. 程序经常访问的文件.sock ...

  3. FastReport经验

    FastReport经验 1.FastReport中如果访问报表中的对象? 可以使用FindObject方法. TfrxMemoView(frxReport1.FindObject(’memo1′)) ...

  4. shell 监控局域网的主机是否up

    #!/bin/bash ;i<;i++)) ;do .$i>/dev/null #ping -c 172.31.0.30 ~172.31.0.59 ]] #if up $?==0 then ...

  5. C# 操作IIS方法集合

    如果在win8,win7情况下报错:未知错误(0x80005000) 见http://blog.csdn.net/ts1030746080/article/details/8741399 using ...

  6. mybatis setting配置

    Mybatis配置报错元素类型为 "configuration" 的内容必须匹配 "(properties?,settings?,typeAliases?,typeHan ...

  7. 【leetcode】Convert Sorted Array to Binary Search Tree (easy)

    Given an array where elements are sorted in ascending order, convert it to a height balanced BST. 有序 ...

  8. 【linux】进程不要开太多,否则系统会卡死!

    今天在跑一个任务,大概像下面这样 python task.py -s input/ input文件夹下有两百多个文件,比如1.txt, 2.txt等等,task.py会顺序读取并做操作. 我想,这不是 ...

  9. py随笔

    while true,无限循环 str.isdigit判断是不是数字 +只能在两个两个相同的类型之间执行 iter(i)将i加入迭代器

  10. vs win32 & MFC 指针默认位置

    一开始win32指针所在的位置是与debug文件夹同级的.即打开打开改程序的第一个文件夹这一级. MFC指针是在第二个debug下头,就是打开第二个project名词的文件夹下头,e.g., &quo ...