題目

題解
–開始以為和那個什麼括号比對一樣,結果要判重,(QAQ)
結果其實是kmp字元串比對
設f[i][j][k]:第i秒時,高度為j,成功比對第k個的方案數
狀态轉移方程式
if(s[k]==‘U’){
f[i+1][j+1][k+1]=(f[i+1][j+1][k+1]+f[i][j][k])%mod;
if(j)f[i+1][j-1][fail[k][0]]=(f[i+1][j-1][fail[k][0]]+f[i][j][k])%mod;
}
else{
f[i+1][j+1][fail[k][1]]=(f[i+1][j+1][fail[k][1]]+f[i][j][k])%mod;
if(j)f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k])%mod;
}
f[i+1][j+1][l]=(f[i+1][j+1][l]+f[i][j][l])%mod;
if(j)f[i+1][j-1][l]=(f[i+1][j-1][l]+f[i][j][l])%mod;
其中fail[k][0]表示用D比對失敗時可以滿足的字首是多長
fail[k][1]表示用U比對失敗時可以滿足的字首是多少
剩下的就是kmp處理fail數組,像我一樣的蒟蒻還是隻有手算模拟
好像也可以用暴力
不管了
反正就是玄學
代碼
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=205;
const int mod=1000000007;
int t;
char s[MAXN];
int l;
long long f[MAXN][MAXN][MAXN];
int next[MAXN];
int fail[MAXN][2];
void calc(){
int k=0;
for(int i=1;i<l;i++){
while(k&&s[k]!=s[i])
k=next[k];
if(s[k]==s[i])
k++;
next[i+1]=k;
}
fail[0][s[0]=='U']=1;
for(int i=1;i<=l;i++){
k=i;
while(k&&s[k]!='U')
k=next[k];
fail[i][1]=k+1;
if(!k&&s[0]=='D')
fail[i][1]=0;
k=i;
while(k&&s[k]!='D')
k=next[k];
fail[i][0]=k+1;
if(!k&&s[0]=='U')
fail[i][0]=0;
}
}
int main(){
// freopen("track.in","r",stdin);
// freopen("track.out","w",stdout);
cin>>t;
cin>>s;
l=strlen(s);
calc();
f[0][0][0]=1;
for(int i=0;i<t;i++)
for(int j=0;j<=min(i,t-i);j++){
for(int k=0;k<l;k++){
if(s[k]=='U'){
f[i+1][j+1][k+1]=(f[i+1][j+1][k+1]+f[i][j][k])%mod;
if(j)
f[i+1][j-1][fail[k][0]]=(f[i+1][j-1][fail[k][0]]+f[i][j][k])%mod;
}
else{
f[i+1][j+1][fail[k][1]]=(f[i+1][j+1][fail[k][1]]+f[i][j][k])%mod;
if(j)
f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k])%mod;
}
}
f[i+1][j+1][l]=(f[i+1][j+1][l]+f[i][j][l])%mod;
if(j)
f[i+1][j-1][l]=(f[i+1][j-1][l]+f[i][j][l])%mod;
}
cout<<f[t][0][l];
return 0;
}