题目训练网址(密码hpuacm): https://cn.vjudge.net/contest/247842

 

                                  Crazy Search

给定一个字符串,其中含有不同的字母数量为m,现在求这个字符串中有多少个长度为n且长的互不相同的字符子串 

举个例子, n=3, m=4 ,字符串 "daababac". 长度为3的不同的子串分别是: "daa"; "aab"; "aba"; "bab"; "bac". 因此, 答案是5. 

Input

第一行是两个整数n,m,,一个空格隔开。 接下来一行是我们要解决的字符串.( 你可以认为字符串的长度不会超过一千六百万。)Orz我读错题了,并不是字符串长度不超过1600万,是合理hash之后的hash的值不超过1600万。Orz原谅我

Output

程序应该输出一个整数,对应于给定文本中所找到的大小为n的不同子字符串的数量。

输入数据

3 4
daababac

输出数据

5
//#include <bits/stdc++.h>
#include <stdio.h>
#include <string.h>
using namespace std;
const int MAXN = (int) 16e6+7;

char str[MAXN];
bool vis[MAXN];
int ascii[256];

int main()
{
    int n, nc;
    while( ~scanf("%d%d", &n, &nc) )
    {
        memset(str, 0, sizeof(str));
        memset(ascii, 0, sizeof(ascii));
        memset(vis, 0, sizeof(vis));

        scanf("%s", str);
        int len = strlen(str);
        for( int i=0; i<len; i++ )
            ascii[str[i]] = 1;      // 标记字母是否出现过
        int cnt = 0;
        for( int i=0; i<256; i++ )
            if( ascii[i] )
                ascii[i] = cnt++;   // 对出现过的字母赋值

        int sum = 0;    //统计第一个长度为n的substring的HashValue存为sum
        for( int i=0; i<n; i++ )
        {
            sum = sum * nc + ascii[str[i]];
        }
        int ans = 0;    // answer
        if( !vis[sum] )
        {
            vis[sum] = 1;
            ans++;
        }
        int pow = 1;
        for( int i=0; i<n-1; i++ )
            pow *= nc;                  // base  1-n
        for( int i=n; i<len; i++ )
        {
            sum -= ascii[str[i-n]] * pow;
            sum *= nc;
            sum += ascii[str[i]];
            if( !vis[sum] )     // 经过运算,如果sun的值没有改变则两个子串相同
            {
                ans ++;
                vis[sum] = 1;
            }
        }
        printf("%d\n", ans);
    }

    return 0;
}

                                                      Oulipo

 

求模式串在待匹配串的出现次数。

Input

第一行是一个数字T,表明测试数据组数。
之后每组数据都有两行:第一行为模式串,长度不大于10000;第二行为待匹配串,长度不大于1000000。所有字符串只由大写字母组成。

Output

每组数据输出一行结果。

Sample Input

4
ABCD
ABCD
ABA
ABABABA
CDCDCDC
CDC
KMP
NAIVE

Sample Output

1
3
0
0
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long  ULL;
const int MAXN = (int) 1e6 + 7;

char s1[MAXN];
char s2[MAXN];
ULL hash_val[MAXN];
ULL power[MAXN];
int main()
{
    int t;
    scanf("%d", &t);

    power[0] = 1;
    for( int i=1; i<MAXN; i++ )
        power[i] = power[i-1] * 31;
    while( t-- )
    {
        memset(hash_val, 0, sizeof(hash_val));
        scanf("%s", s1+1);
        scanf("%s", s2+1);
        ULL base = 31;
        int len1 = strlen(s1+1);
        int len2 = strlen(s2+1);
        ULL val = 0;
        for( int i=1; i<=len1; i++ )
        {
            val = val * base + s1[i];
        }
        hash_val[0] = 0;
        for( int i=1; i<=len2; i++ )
        {
            hash_val[i] = hash_val[i-1] * base + s2[i];
        }
        int ans = 0;
        for( int i=len1; i<=len2; i++ )
        {
            if( hash_val[i] - hash_val[i-len1] * power[len1] == val )
                ans ++;
        }
        printf("%d\n", ans);
    }

    return 0;
}