I.考前抱佛jio记
Talk is cheap show me the code.
I.I 字符串系列
I.I.I Hash
想必是不用说了。
I.I.II 前缀函数与 Knuth-Morris-Pratt 算法
I.I.II.I 计算前缀函数
算法1:枚举
复杂度(Theta(n^3))
vector<int> prefix_function(char *s){
int n = strlen(s+1);
vector<int> pi(n);
for(int i=1; i<=n; i++){
for(int j=i; j>=0; j--){
bool flag = 1;
for(int k=1; k<=j; k++){
if(str[k] != str[i-k+1]){
flag = 0;
break;
}
}
if(flag){
pi[i] = j;
break;
}
}
}
return pi;
}
优化1:相邻前缀函数至多增加1
复杂度(Theta(n^2))
vector<int> prefix_function(char *s){
int n = str(s+1);
vector<int> pi(n);
for(int i=1; i<=n; i++){
for(int j=pi[i-1]+1; j>=0; j--){
bool flag = 1;
for(int k=1; k<=j; k++){
if(str[k] != str[i-k+1]){
flag = 0;
break;
}
}
if(flag){
pi[i] = j;
break;
}
}
}
return pi;
}
优化2:失配指针
复杂度(Theta(n))
vector<int> prefix_function(char *s){
int n = str(s+1);
vector<int> pi(n);
for(int i=1; i<=n; i++){
int j = pi[i-1];
while(j and s[i] != s[j+1]) j = pi[j-1];
if(s[i] == s[j+1]) j ++;
pi[i] = j;
}
return pi;
}
I.I.II.II Knuth-Morris-Pratt algorithm
复杂度(Theta(n+m))
vector<int> Knuth_Morris_Pratt_algorithm(char *s, char *p){
int n = str(s+1), m = str(p+1);
vector<int> pos, nxt;
nxt = prefix_function(char *p);
for(int i=1, j=0; i<=n; i++){
while(j and s[i] != p[j+1]) j = nxt[j];
if(p[j+1] == s[i]) j ++;
if(j == m) pos.push_back(i-j+1);
}
return pos;
}
(字符串系列未完待续,咕咕咕~)
I.II 数学系列
I.II.I 从快速幂开始
int qpow(int x, int y){
int cnt = 1, basic = x;
while(y){
if(y&1) cnt = cnt*basic;
basic = basic*basic, y >>= 1;
}
return cnt;
}
矩阵类
struct Matrix
{
int a[maxn][maxn], n;
void clear(int x)
{
n = x;
for (int i = 1; i <= n; i++)
a[i][i] = 1;
}
void init(int x)
{
n = x;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = 0;
}
Matrix operator*(const Matrix &x) const
{
Matrix c;
c.init(n);
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
(c.a[i][j] += a[i][k] * x.a[k][j] % mod) %= mod;
return c;
}
void debug()
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
};
I.II.II 从gcd开始
int gcd(int x, int y){
if(y == 0) return x;
return gcd(y, x%y);
}
I.II.III 扩展欧几里得EX-gcd
定理:裴蜀定理
[ax+by=gcd(a,b) ]
简单推导:
[ax+by=(a,b)=(b,a\%b)=bx'+(a\%b)y'=bx'+(a-bcdotleftlfloor dfrac{a}{b}
ight
floor)y'\ herefore egin{cases}x=y'\y=x'-leftlfloorfrac{a}{b}
ight
floor y'end{cases}
]