zoukankan      html  css  js  c++  java
  • 【POJ2752】Seek the Name, Seek the Fame-KMP思想

    测试地址:Seek the Name, Seek the Fame

    题目大意:多组测试数据,每组给定一个字符串S,要求求出既是S前缀又是S后缀的子串的所有可能长度。

    做法:乍一看这题好像无从下手,但其实我们仔细观察这种性质,就可以发现这个过程和KMP中求next函数的过程是相似的,把S当成模式串来计算next函数,最后一个字符时特殊处理,用与计算next函数过程中寻找最大公共长度的循环相似的过程,可以看出可以取到的index的值表示除最后一个字符外的S串中,前index个字符和后index个字符是相同的,这时只要比对第index+1个字符和最后一个字符是否相等,如果相等,则index+1为一个可能的答案,与平常计算next函数的过程的唯一不同,就是验证相等后并不马上结束,而是寻找所有可能的情况,由于我们找到的答案呈降序排列,而题目要求输出升序,反过来输出即可,最后输出S串的长度即可(因为整个S串一定是它自己的前缀与后缀,并且这个值我们在前面没有能计算出来,所以需要额外输出)。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    char p[400010];
    int overlay[400010],ans[400010],lenp;
    
    void calc_overlay()
    {
      int index;
      overlay[0]=0;
      for(int i=1;i<lenp-1;i++)
      {
        index=overlay[i-1];
    	while(index>=1&&p[index]!=p[i])
    	{
    	  index=overlay[index-1];
    	}
    	if (p[index]==p[i]) overlay[i]=index+1;
    	else overlay[i]=0;
      }
    }
    
    int main()
    {
      while(scanf("%s",p)!=EOF)
      {
        lenp=strlen(p);
        calc_overlay();
    	if (lenp==1) {printf("1
    ");continue;}
    	else
    	{
    	  int index;
    	  ans[0]=0;
    	  index=overlay[lenp-2];
    	  while(index>=0)
    	  {
    	    if (p[index]==p[lenp-1]) ans[++ans[0]]=index+1;
            if (index==0) break;
    		index=overlay[index-1];
    	  }
    	  for(int i=ans[0];i>=1;i--) printf("%d ",ans[i]);
    	  printf("%d
    ",lenp);
    	}
      }
      
      return 0;
    }
    


  • 相关阅读:
    inner join on, left join on, right join on讲解(转载)
    ref 与 out
    Shell基础01
    Python 基础01
    linux基础03
    Shell基础02
    linux基础02
    Linux基础01
    linux基础05
    linux基础04
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793860.html
Copyright © 2011-2022 走看看