zoukankan      html  css  js  c++  java
  • 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
    ",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);
    }
  • 相关阅读:
    设计模式之工厂模式-抽象工厂(02)
    1036 跟奥巴马一起编程 (15 分)
    1034 有理数四则运算 (20 分)
    1033 旧键盘打字 (20 分)
    1031 查验身份证 (15 分)
    大学排名定向爬虫
    1030 完美数列 (25 分)二分
    1029 旧键盘 (20 分)
    1028 人口普查 (20 分)
    1026 程序运行时间 (15 分)四舍五入
  • 原文地址:https://www.cnblogs.com/handsomecui/p/4710836.html
Copyright © 2011-2022 走看看