Power Strings
Time Limit : 6000/3000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 29 Accepted Submission(s) : 14
Problem Description
Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).
Input
Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.
Output
For each s you should print the largest n such that s = a^n for some string a.
Sample Input
abcd aaaa ababab .
Sample Output
1 4 3
题解:让找串的重复度;
描述:
对于数组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。
n-next[n]也就是当前最小匹配的字串长度。。。。。此处的next数组相当于代码中的p数组......
代码:
1 #include<stdio.h> 2 #include<string.h> 3 const int MAXN=1000010; 4 int p[MAXN]; 5 char s[MAXN]; 6 int n,len; 7 void getp(){ 8 int i=0,j=-1; 9 p[0]=-1; 10 while(i<len){ 11 if(j==-1||s[j]==s[i]){ 12 i++;j++; 13 p[i]=j; 14 } 15 else j=p[j]; 16 } 17 } 18 int main(){int answer; 19 while(scanf("%s",s),strcmp(s,".")){ 20 memset(p,0,sizeof(p)); 21 len=strlen(s); 22 getp(); 23 /*for(int i=0;i<=len;i++)printf("%d ",p[i]); 24 puts("");*/ 25 answer=1; 26 if(len%(len-p[len])==0)answer=len/(len-p[len]); 27 printf("%d ",answer); 28 } 29 return 0; 30 }
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; #define mem(x,y) memset(x,y,sizeof(x)) #define SI(x) scanf("%d",&x) #define PI(x) printf("%d",x) const int INF=0x3f3f3f3f; const int MAXN=1000010; int p[MAXN]; void getp(char* s){ int len=strlen(s); int i=0,j=-1; p[0]=-1; while(i<len){ if(j==-1||s[i]==s[j]){ i++;j++; p[i]=j; } else j=p[j]; } } int main(){ char s[MAXN]; while(~scanf("%s",s),strcmp(s,".")){ getp(s); int len=strlen(s); if(len==0){ puts("0");continue; } if(p[len]!=-1&&len%(len-p[len])==0){ printf("%d ",len/(len-p[len])); } else puts("1"); } return 0; }
下面是修正过的:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> typedef long long LL; const int MAXN = 1000010; char s[MAXN]; int next[MAXN]; void getp(){ int i = 0, j = -1; next[i] = j; while(s[i]){ if(j == -1 || s[i] == s[j]){ i++;j++; next[i] = j; if(s[i] == s[j]) next[i] = next[j]; } else j = next[j]; } } int main(){ while(scanf("%s", s), s[0] != '.'){ getp(); int len = strlen(s); // for(int i = 0; i <= len; i++){ // printf("%d ", next[i]);}puts(""); if(len % (len - next[len]) == 0 && len / (len - next[len]) > 1){ printf("%d ", len / (len - next[len])); } else puts("1"); } return 0; }
java写法:
import java.util.Scanner; public class kmp{ public static class newkmp extends kmpmod{ public void work(char[] str){ getp(str); //System.out.print(p[len]); if(len % (len - p[len]) == 0) System.out.println(len/(len - p[len])); else System.out.println(1); } } public static char[] str = new char[1000010]; public static void main(String[] argv){ Scanner cin = new Scanner(System.in); newkmp kmp1 = new newkmp(); while(cin.hasNext()){ str = cin.next().toCharArray(); if(str.length == 1 && str[0] == '.') break; //System.out.print(str); kmp1.work(str); } } } abstract class kmpmod{ protected int p[] = new int[1000010]; protected int len; public void getp(char[] str){ for(int i = 0; i < p.length; i++){ p[i] = 0; } len = str.length; int i = 0, j = -1; p[0] = -1; while (i < str.length) { if(j == -1 || str[i] == str[j]){ i++; j++; p[i] = j; } else{ j = p[j]; } } } public abstract void work(char[] str); }