zoukankan      html  css  js  c++  java
  • 「UVA1328」Period 解题报告

    English题面

    题意:

    给你一个长度为n的字符串,依次取字符串前i个(前缀),如果前缀由k(k>0)个相同真子串构成,那么输出i和k

    直到n为0结束,每组数据后要有一行空白

    思路:

    KMP+一点点判断

    其实这道题并不是很难

    可以先用KMP求出最长的s[1~i]的前缀和后缀的真子串的长度j

    话说的有点复杂,分开来理

    1、真子串:

    不是字符串本身的子串

    2、是s[1~i]的前缀和后缀:

    aabaab为例

    aabaab

    aabaab

    aab是aabaab的前缀,又是后缀

    j=3

    两种条件下:

    以aaa为例

    就应该是

    aaa

    aaa

    aa是aaa的前缀&后缀&真子串

    j=2

    判断方法

    if(i%(i-j)==0) //说明循环的子串长度为i-j,循环次数为i/(i-j)

    证明:

    RT:

    (ecause) l=r

    ( herefore) ①=①,②=②,③=③

    ( herefore) ①=②=③

    其他情况无论多少都可以这样 连等,只要i-j能够整除i那么就是成立的

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    string s;
    int n,t;
    int len,cur;
    int p[1000010];
    int read()
    {
    	int s=0;
    	char c=getchar();
    	while(!isdigit(c))
    		c=getchar();
    	while(isdigit(c))
    	{
    		s=(s<<1)+(s<<3)+c-'0';
    		c=getchar();
    	}
    	return s;
    }
    int main()
    {
    	int i,j;
    	n=read();
    	while(n)
    	{
    		printf("Test case #%d
    ",++t);
    		cin>>s;
    		len=s.size();
    		for(i=len;i;i--)
    			s[i]=s[i-1];
    		for(i=2,j=0;i<=len;i++)//KMP大法
    		{
    			while(j&&s[i]!=s[j+1])//求前缀的那个东东
    				j=p[j];
    			if(s[i]==s[j+1])
    				j++;
    			p[i]=j;
    			if(j>=(i>>1)&&i%(i-j)==0)//判断一下
    				printf("%d %d
    ",i,i/(i-j));
    		}
    		printf("
    ");
    		n=read();
    	}
    	return 0;
    }
    

    友情链接

    KMP百度百科

    【模板】KMP字符串匹配

  • 相关阅读:
    快速排序——中位数
    DataGridView 在下拉框添加下来事件
    VS2015 调试时 编辑并继续不可用
    用soapUI测试webservice
    SQL Server 2008 表变量 临时表
    mvc 返回值
    asp.net 页面上的点击事件
    C# SQL 面试题自我总结
    cf contest 1458
    【CFR#655】F Omkar ans Modes
  • 原文地址:https://www.cnblogs.com/hovny/p/10136197.html
Copyright © 2011-2022 走看看