1. 程式人生 > >ACM學習歷程23——最小週期串問題

ACM學習歷程23——最小週期串問題

最小週期串問題屬於字串操作的基本題型之一,要求給定一個字串找出其中最小的週期長度和最小週期子串。對於週期串的定義如下:如果一個字串是以一個或者一個以上的長度為K的重複字串連線成的,那麼這個字串就叫做週期為K的串。找最小週期串的方法可以通過以下方式實現:

一、從字串的起始位置遍歷,對於字串長度為N的字串,那麼週期串的可能長度介於1—N之間,所以可以假設週期串的長度為i,其中1<=i<=N。滿足最小週期串的條件之一是length%i==0,這是因為如果所述i是字串的週期串長度,那麼整個字串可以被劃分成整數個長度為i的週期子串,如果這個整除的條件不成立,說明i也不是字串的週期串長度。滿足最小週期串的條件之二是,變數j從i的位置開始一直到字元處結束的位置,滿足(s[j]!=s[j%i])這個條件,這是因為若從0到i-1這個區間組成的子串是該字串的週期串,那麼從i到length-1的位置是該最小字串的若干次重複。由於上述i的取值是從1即從最小值開始取值的,因此當上述兩個條件都成立時,即可求得最小週期串長度和最小週期串。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	int i,j;
	int flag;//判斷最小週期串是否找到,找到值為1,否則為0
	char ss[100];
    string s;
	while(cin.getline(ss,100))
	{
		s=ss;
		int length=s.length();
		for(i=1;i<=length;i++)
		{
			if(length%i==0)
			{
				flag=1;
				for(j=i;j<length;j++)
				{
					if(s[j]!=s[j%i])
					{
						flag=0;
						break;
					}
				}
				if(flag)
				{
					cout<<"The cycle="<<i<<endl;
					cout<<"The minimum string="<<s.substr(0,i)<<endl;
					break;
				}
			}
		}
	}
	return 0;
}
測試結果:
121212
The cycle=2
The minimum string=12
1234512345
The cycle=5
The minimum string=12345
二、下面的程式碼實現方式原理和上述一樣,只是在迴圈的部分略有區別,但思想是一樣的,直接上程式碼。
#include<iostream>
#include<string>
using namespace std;

int main()
{
	int i;
	char ss[100];
	string s;
	while(cin.getline(ss,100))
	{
		s=ss;
		int length=s.length();
		for(i=1;i<=length;i++)
		{
			if(length%i==0)
			{
				int j=i,k=0,N=1;
				while(j<length && k<i)
				{
					if(s[j]==s[k])
					{
						j++;
						k++;
						if(k==i)
						{
							k=0;
							N++;
						}
					}
					else
					{
						N=1;
						break;
					}
				}
				if(j==length)
				{
					cout<<"T="<<i<<endl;
					cout<<"N="<<N<<endl;
					cout<<"The minimum string="<<s.substr(0,i)<<endl;
					break;
				}
			}
		}
	}
	return 0;
}
測試結果:
123123
T=3
N=2
The minimum string=123