进制哈希(自然溢出)

进制哈希(自然溢出)

计算单个字符串哈希值

typedef unsigned long long ull;
ull strhash(string &s){
ull H=0,P=131; 
for(char c:s){ 
H=H*P+c; 
} 
return H;
}
计算字符串每一个前缀的哈希
typedef unsigned long long ull;
vector<ull> strhash(string &s){ 
vector<ull> vec; 
ull H=0,P=131; 
for(char c:s){ 
H=H*P+c; 
vec.push_back(H); 
}   
return vec;
}

计算字符串子串哈希值

typedef unsigned long long ull;
const int N=1e6;
ull P=131;
vector<ull>PP{1};
void init(){ 
for(int i=1;i<=N;i++){ 
PP.push_back(PP.back()*P);
}
}
vector<ull> strhash(string &s){ 
vector<ull> vec; 
ull H=0; 
for(char c:s){ 
H=H*P+c; 
vec.push_back(H); 
} 
return vec;
}
ull gethash(vector<ull> &has,int l,int r){ 
if(l==0) return has[r]; 
return has[r]-has[l-1]*PP[r-l+1];
}
 
 

Dmitry has a string �s, consisting of lowercase Latin letters.

Dmitry decided to remove two consecutive characters from the string �s and you are wondering how many different strings can be obtained after such an operation.

For example, Dmitry has a string "aaabcc". You can get the following different strings: "abcc"(by deleting the first two or second and third characters), "aacc"(by deleting the third and fourth characters),"aaac"(by deleting the fourth and the fifth character) and "aaab" (by deleting the last two).

Input

The first line of input data contains a single integer �t (1≤�≤1041≤t≤104) — number of test cases.

The descriptions of the test cases follow.

The first line of the description of each test case contains an integer �n (3≤�≤2⋅1053≤n≤2⋅105).

The second line of the description of each test case contains a string �s of length �n consisting of lowercase Latin letters.

It is guaranteed that the sum of �n for all test cases does not exceed 2⋅1052⋅105.

Output

For each test case print one integer — the number of distinct strings that can be obtained by removing two consecutive letters.

Sample 1

Inputcopy Outputcopy
7
6
aaabcc
10
aaaaaaaaaa
6
abcdef
7
abacaba
6
cccfff
4
abba
5
ababa
4
1
5
3
3
3
1

Note

The first example is explained in the statement.

In the third example, the following strings are obtained: "cdef", "adef", "abef", "abcf", "abcd".

In the seventh example, any deletion will result in the string "aba".

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;

const int N=1e6;
ull P=1007;
vector<ull>PP{1};

void init(){//* 计算字符子串哈希值 
    for(int i=1;i<=N;i++){
        PP.push_back(PP.back()*P);
    }
}

vector<ull> strhash(string &s){//计算字符串每一个前缀的哈希 
    vector<ull> vec;
    ull H=0;
    for(char c:s){
        H=H*P+c;
        vec.push_back(H);
    }
    return vec;
}

ull gethash(vector<ull> &has,int l,int r){
    return has[r]-has[l-1]*PP[r-l+1];
}//*

void sol(){
    int n;cin>>n;
    string s;cin>>s;
    s="$"+s;
    vector<ull>has(strhash(s));
    vector<ull>vec;
    for(int i=1;i<=n;i++){
        ull pre=has[i-1];
        ull suf=gethash(has,i+2,n);
        
        vec.push_back(pre*PP[n-i-1]+suf);
    }
    sort(vec.begin(),vec.end());//去重 
    cout<<unique(vec.begin(),vec.end())-vec.begin()-1<<endl;//计算不同的个数 
}


int main(){
    
    init();
    int t;cin>>t;
    while(t--)sol();
    
    return 0;
}

A - 进制哈希模板题

Description

如题,给定 �N 个字符串(第 �i 个字符串长度为 ��Mi​,字符串内包含数字、大小写字母,大小写敏感),请求出 �N 个字符串中共有多少个不同的字符串。

Input

第一行包含一个整数 �N,为字符串的个数。

接下来 �N 行每行包含一个字符串,为所提供的字符串。

Output

输出包含一行,包含一个整数,为不同的字符串个数。

Sample 1

Inputcopy Outputcopy
5
abc
aaaa
abc
abcc
12345
4

Hint

对于 30%30% 的数据:�≤10N≤10,��≈6Mi​≈6,����≤15Mmax≤15。

对于 70%70% 的数据:�≤1000N≤1000,��≈100Mi​≈100,����≤150Mmax≤150。

对于 100%100% 的数据:�≤10000N≤10000,��≈1000Mi​≈1000,����≤1500Mmax≤1500。

样例说明:

样例中第一个字符串(abc)和第三个字符串(abc)是一样的,所以所提供字符串的集合为{aaaa,abc,abcc,12345},故共计4个不同的字符串。

#include<iostream>//a
#include<vector>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;

ull strhash(string &s){
    ull H=0,P=131;
    for(char c:s){
        H=H*P+c;
    }
    return H;
}


int main(){
    int n;cin>>n;
    vector<ull>vec;
    
    for(int i=1;i<=n;i++){
        string s;cin>>s;
        vec.push_back(strhash(s));
    }
    sort(vec.begin(),vec.end());
    cout<<unique(vec.begin(),vec.end())-vec.begin()<<endl;

猜你喜欢

转载自blog.csdn.net/m0_74310050/article/details/130229388