1. 程式人生 > >5481: 問君能有幾多愁

5481: 問君能有幾多愁

rom CI 最大數 就是 ace 小寫 pre mes 最大

描述

任何人都喜歡解決難題,其中一些可能會導致瘋狂(比如害死人不償命的(3n+1)猜想 )。

問君能有幾多愁?恰似一江春水向東流。

一個難題就是找到給定字符串中不同子串的數目。聰明的人也是無法很快解決這個問題的,但是計算機可以的啊。你需要計算機的幫助和一個很好的算法來解決這樣一個難題。

給定要尋找的子串的長度n,字符串出現的不同字符數nchar和字符串s,求出字符串s中出現的長度為n的不同子串的數目。

舉一個例子,n=3,nchar=4和字符串“daababac”。在字符串s可以找到大小為3的不同子串是:"daa","aab","aba","bab","bac"。因此,答案應該是5。

輸入

輸入數據有多組。

每組第一行由兩個數字n和nchar組成。

第二行為給定小寫字母組成的字符串s。數據保證由可能的字符集所形成的子串的最大數目不超過1600000。

n不超過8,nchar不超過26,s的長度不超過1e6。

輸出

每組輸出一個整數,對應於給定字符串中找到的大小n的不同子串的數目。

樣例輸入

3 4
daababac
1 2
aba

樣例輸出

5
2

解題思路:哈希可能的字符串,has[i]=has[i-1]*p+idx(s[i]);

對於第一個樣例(從1開始)

daa:

has[1]=4,has[2]=(4*27)+1,has[3]=(4*27+1)*27+1;

aab:

has[4]=1,has[5]=(1*27+1),has[6]=(1*27+1)*27+2;

所以has[6]=(has[3]%(27*27)*27+2);

#include <bits/stdc++.h>
using namespace std;
char a[1000002];
int main()
{
    int n,m,i,j,k;
    while(cin>>n>>m)
    {
        scanf("%s",a+1);
        set <long long> se;
        
long long t=1,sum=0,len=strlen(a+1); for(i=1;i<n;i++) t=t*27; for(i=1;i<=len;++i) { if(i<=n) sum=sum*27+(a[i]-a+1); if(i==n) se.insert(sum); if(i>n) { sum=(sum%t)*27+(a[i]-a+1); se.insert(sum); } } cout<<se.size()<<endl; } return 0; }

5481: 問君能有幾多愁