题目大意
给定一个字符串,给出一种操作为,选定一个字符(第一个除外),将从这个字符开始到字符串最后的这一部分子串放到字符串的最前面。
给出两个串,问经过k次操作有多少种方案能够从第一个串得到第二个串。
题解
这个操作其实就是把串看成一个环,每次选一个字符来当头。
设字符串长度为n,那么我们通过操作只可能得到n个子串。考虑除了原串外其他串经过若干次操作能够被得到的方案数都是一样的,定义
fi,0
为经过i次操作能够得到原串的方案数,
fi,1
为经过i次操作能够得到其他串的方案数。
那么:
fi,0=fi−1,1×(n−1)
fi,1=fi−1,0+fi−1,1∗(n−2)
再考虑第二个串能在多少位置和第一个串完全匹配(环状)答案就是多少倍的 fk,1 。特殊的,如果第二个串和第一个串完全相同,即在第一个位置就完全匹配,那么加上的是 fk,0 。
#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(int i = (l); i <= (r); i++)
typedef long long ll;
const int N = 1000 + 10, mod = 1000000000 + 7;
char s[N], t[N];
int k, n;
ll f[2][2], ans;
void init(){
scanf("%s%s%d", s, t, &k);
n = strlen(s);
}
void work(){
f[0][0] = 1;
rep(i, 1, k){
f[i&1][0] = (f[i&1^1][1] * (n - 1)) % mod;
f[i&1][1] = (f[i&1^1][0] + f[i&1^1][1] * (n - 2)) % mod;
}
int ok;
rep(i, 0, (n - 1)){
ok = 1;
rep(j, 0, (n - 1))
if(s[(j+i)%n] != t[j]){
ok = 0;
break;
}
if(ok)
if(i == 0) ans += f[k&1][0];
else ans += f[k&1][1];
ans %= mod;
}
cout<<ans<<endl;
}
int main(){
init();
work();
return 0;
}
upd:
将f的计算过程改为矩阵快速幂,两串的匹配过程改为hash,可通过字符串长度
106
,
k≤1012
的数据。
#include<bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for(register int i = (l); i <= (r); i++)
#define per(i, r, l) for(register int i = (r); i >= (l); i--)
#define ll long long
#define ull unsigned long long
const int N = 1000 + 10, mo = 1000000000 + 7;
char s[N], t[N];
int k, n;
ll ans;
ull pw[N], hs[N], ht[N];
struct M{
ll dat[2][2];
M(){memset(dat, 0, sizeof(dat));}
}f, e;
void mul(M &a, M &b){
M ret;
rep(i, 0, 1) rep(j, 0, 1) rep(k, 0, 1)
ret.dat[i][j] = (ret.dat[i][j] + a.dat[i][k] * b.dat[k][j]) % mo;
rep(i, 0, 1) rep(j, 0, 1) a.dat[i][j] = ret.dat[i][j];
}
void poww(M &a, int b){
M ret;
ret.dat[0][0] = ret.dat[1][1] = 1;
while(b){
if(b & 1) mul(ret, a);
mul(a, a);
b >>= 1;
}
rep(i, 0, 1) rep(j, 0, 1) a.dat[i][j] = ret.dat[i][j];
}
void cal(ll &a, ll &b){
rep(i, 0, n - 1)
if(hs[i] + (hs[0] - hs[i] * pw[i]) * pw[n-i] == ht[0])
if(!i) a++;
else b++;
}
void init(){
scanf("%s%s%d", s, t, &k);
n = strlen(s);
pw[0] = 1;
rep(i, 1, n) pw[i] = pw[i-1] * 27;
hs[n-1] = s[n-1];
ht[n-1] = t[n-1];
per(i, n - 2, 0){
hs[i] = hs[i+1] * 27 + s[i];
ht[i] = ht[i+1] * 27 + t[i];
}
f.dat[0][0] = 1;
e.dat[0][1] = n - 1;
e.dat[1][0] = 1, e.dat[1][1] = n - 2;
}
void work(){
poww(e, k);
mul(e, f);
ll a(0), b(0);
cal(a, b);
cout<<(a * e.dat[0][0] % mo + b * e.dat[1][0] % mo) % mo << endl;
}
int main(){
freopen("176b.in", "r", stdin);
freopen("176b.out", "w", stdout);
init();
work();
return 0;
}