目录
字符串Hash
定义
Hash是种单射函数,可将万物单向映射成一个整数值。
字符串Hash通过把字符串S映射成一个整数值H(S)来快速比较(O(1))两个字符串是否相等。
性质
S=T→H(T)=H(S)
(必要性、非充分性)
多项式取模Hash
方法:把S看成某进制(base)下的数字串,并将得到的H(S)对一个尽量大(接近n²,n是Hash检验次数)的质数取模。
公式:H(S)=H(S[1,|S|-1])*BASE+S[|S|];
自然溢出
用ULL保存Hash,自然溢出(肯定会被卡掉)。
双模Hash
在不泄露模数的情况下,没有已知方法可以构造冲突。
const int mod1 = 1000000007;
const int mod2 = 1000000009;
板子
子串的基础定义
S[l,r]
表示字符串S从第l个到第r个字母顺次连接成的新字符串。
PrefixS[i]
字符串S长度为i的前缀(1~i);
SuffixS[i]
字符串S长度为i的后缀(n-i+1~n);
获得子串Hash值的方法
H(l,r) = H(r)-H(l-1)*pow(base,r-l+1)
例题:Seek the Name, Seek the Fame
The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm:
Step1. Connect the father's name and the mother's name, to a new string S.
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).
Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:)
Input
The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.
Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000.
Output
For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.
Sample
Inputcopy | Outputcopy |
---|---|
ababcababababcabab aaaaa | 2 4 9 18 1 2 3 4 5 |
简析:先预处理hash和pow并写出get函数。
#ifndef _GLIBCXX_NO_ASSERT
#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#if __cplusplus >= 201103L
#include <ccomplex>
#include <cfenv>
#include <cinttypes>
#include <cstdalign>
#include <cstdbool>
#include <cstdint>
#include <ctgmath>
#include <cuchar>
#include <cwchar>
#include <cwctype>
#endif
// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <codecvt>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif
#if __cplusplus >= 201402L
#include <shared_mutex>
#endif
#if __cplusplus >= 201703L
#include <charconv>
#include <filesystem>
#endif
using namespace std;
typedef unsigned long long ull;
ull n,p[400002]={1},h[400002]={0},b=131;
string s;
ull get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
void solve()
{
n=s.size();
char str[400002];
for(int i=1;i<=n;i++)
{
str[i]=s[i-1];
p[i]=p[i-1]*b;
h[i]=h[i-1]*b+str[i]-'0';
}
for(int i=1;i<=n;i++)
{
if(get(1,i)==get(n-i+1,n))
{
cout<<i;
if(i<n)cout<<' ';
}
}
}
int main()
{
while(cin>>s)
{
solve();
cout<<'\n';
}
}