• POJ 1961/POJ 2406 /POJ 2752 /【KMP应用】


    昨天把KMP复习了一下,顺便做了一些以前做过的题,貌似有那么点感觉O(∩_∩)O~
    贴出来,方便以后复习,O(∩_∩)O~
    http://poj.org/problem?id=1961
    POJ 1961 Period
    大意:
       定义字符串A,若A最多由n个相同字串s连接而成,则A=s^n,如"aaa" = "a"^3,"abab" = "ab"^2
       "ababa" = "ababa"^1
       
    给出一个字符串A,求该字符串的所有前缀中有多少个前缀SA= s^n(n>1)
    输出符合条件的前缀长度及其对应的n
    
      如aaa
      前缀aa的长度为2,由2个'a'组成
      前缀aaa的长度为3,由3个"a"组成
    
      分析:KMP
      若某一长度L的前缀符合上诉条件,则
        1.next[L]!=0(next[L]=0时字串为原串,不符合条件)
    	2.L%(L-next[L])==0(此时字串的长度为L/next[L])
    
     对于2:有str[0]....str[next[L]-1]=str[L-next[L]-1]...str[L-1]
            =》str[L-next[L]-1] = str[L-next[L]-1+L-next[L]-1] = str[2*(L-next[L]-1)];
    		假设S = L-next[L]-1;则有str[0]=str[s]=str[2*s]=str[3*s]...str[k*s],对于所有i%s==0,均有s[i]=s[0]
    		同理,str[1]=str[s+1]=str[2*s+1]....
    		      str[j]=str[s+j]=str[2*s+j]....
    	    综上,若L%S==0,则可得L为str[0]...str[s-1]的相同字串组成,
    		总长度为L,其中字串长度SL = s-0+1=L-next[L],循环次数为L/SL
            故对于所有大于1的前缀,只要其符合上述条件,即为答案之一
    
    
    View Code
    #include<stdio.h>
    #include
    <string.h>
    const int N = 1000000+10;
    char str[N];
    int next[N];
    int len;
    void GetNext1(char str[N],int next[N])//寻找模式串的粗略next
    {
    int l=strlen(str);
    next[
    0]=-1;
    int i=0,j=-1;
    while(i<l)
    {
    if(j==-1||str[i]==str[j])
    {
    i
    ++;j++;
    next[i]
    =j;
    }
    else
    j
    =next[j];
    }
    }
    int main()
    {
    int T = 0;
    while(scanf("%d",&len)!=EOF)
    {
    T
    ++;
    if(len == 0)break;
    scanf(
    "%s",str);
    GetNext1(str,next);
    int i;
    printf(
    "Test case #%d\n",T);
    for(i=2;i<=len;i++)
    {
    if(next[i]!=0&&i%(i-next[i])==0)//保证不是原串且循环
    {
    printf(
    "%d %d\n",i,i/(i-next[i]));
    }
    }

    printf(
    "\n");
    }
    return 0;
    }

    http://poj.org/problem?id=2406
    POJ 2406 Power Strings
    大意:给出一个字符串S,求该字符串最多是由相同重复字串连接而成的
    若S由n个A组成,则称 S = A^n,求最大的n
      如 S=aaa,S="a"^3 => n = 3;
         S=ababa =>  n = 1
    分析:KMP
       与POJ 1961类似,而且更简单:
        若L%(L-next[L])==0,n = L/(L-next[L]),else n = 1
    View Code
    #include<stdio.h>
    #include
    <string.h>
    const int N = 1000000+10;
    char str[N];
    int next[N];
    int len;
    void GetNext1(char str[N],int next[N])//寻找模式串的粗略next
    {
    int l=strlen(str);
    next[
    0]=-1;
    int i=0,j=-1;
    while(i<l)
    {
    if(j==-1||str[i]==str[j])
    {
    i
    ++;j++;
    next[i]
    =j;
    }
    else
    j
    =next[j];
    }
    }
    int main()
    {
    int T = 0;
    while(scanf("%s",str)!=EOF)
    {
    if(strcmp(str,".")==0)break;
    GetNext1(str,next);
    int len = strlen(str);
    if(len%(len-next[len])==0)
    printf(
    "%d\n",len/(len-next[len]));
    else
    printf(
    "1\n");
    }
    return 0;
    }

    http://poj.org/problem?id=2752
    POJ 2752 Seek the Name, Seek the Fame
    大意:
    给出一个字符串A,求A有多少个前缀同时也是后缀,从小到大输出这些前缀的长度
    
    分析:KMP
    对于长度为len的字符串,由next的定义知:
    A[0]A[1]...A[next[len]-1]=A[len-next[len]]...A[len-1]此时A[0]A[1]...A[next[len]-1]为一个符合条件的前缀
    有A[0]A[1]....A[next[next[len]]-1] = A[len-next[next[len] - next[next[len]]]...A[next[len]-1],故A[0]A[1]....A[next[next[len]]-1]也是一个符合条件的前缀
    故从len=>next[len]=>next[next[len]] ....=>直到某个next[]为0均为合法答案,注意当首位单词相同时,也为答案。
    
    
    View Code
    #include<stdio.h>
    #include
    <string.h>
    #include
    <vector>
    using namespace std;
    vector
    <int>ans;
    const int N = 1000000+10;
    char str[N];
    int next[N];
    void GetNext1(char str[N],int next[N])//寻找模式串的粗略next
    {
    int l=strlen(str);
    next[
    0]=-1;
    int i=0,j=-1;
    while(i<l)
    {
    if(j==-1||str[i]==str[j])
    {
    i
    ++;j++;
    next[i]
    =j;
    }
    else
    j
    =next[j];
    }
    }
    int main()
    {
    while(scanf("%d",&str)!=EOF)
    {
    scanf(
    "%s",str);
    GetNext1(str,next);
    int cur,len;
    len
    = strlen(str);
    cur
    = len;
    ans.clear();
    while(cur)
    {
    ans.push_back(cur);
    cur
    = next[cur];
    }

    if(str[0]==str[len])//首位字符相同
    ans.push_back(1);
    int sz = ans.size();
    for(cur = sz-1;cur>0;cur--)
    printf(
    "%d ",ans[cur]);
    printf(
    "%d\n",ans[0]);
    }
    return 0;
    }
  • 相关阅读:
    《决战大数据:驾驭未来商业的利器》作者离阿里的业务太远,比另外三本阿里人写的优秀的图书差不少,二星,不推荐。
    《硅谷百年史》:比较可信的硅谷的历史。缺点是趣味性稍差。五星推荐
    转贴健康资讯:艰辛的疫苗接种之路
    《美国大城市的死与生》:1961年出版的城市规划方面的经典,国内许多大城市的规划方面的弊病都被本书言中了
    转贴健康资讯:体检时的辐射会致癌吗?
    《国家为什么会崩溃》:美国政府正在陷入互联网泡沫、房地产泡沫之后的第三个泡沫:政府泡沫 五星推荐
    转贴健康资讯:仰睡、反仰睡、仰睡
    [HTML5] How Visible vs. Hidden Elements Affect Keyboard/Screen Reader Users (ARIA)
    [Angular] Component's dependency injection
    [HTML5] Accessible Icon Buttons
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1984772.html
Copyright © 2020-2023  润新知