Power Strings(kmp妙解)

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\n",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\n",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\n", 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);
}

 

posted @ 2015-08-07 15:08  handsomecui  阅读(473)  评论(0编辑  收藏  举报