Codeforces Round #820 (Div. 3) G. Cut Substrings dp计数 把主串中所有跟子串匹配的位置删掉
https://codeforces.ml/contest/1729/problem/G
https://zhuanlan.zhihu.com/p/563809110
分析:
就是把主串中所有跟子串匹配的位置删掉,问最少删除多少次能够满足主串中不再出现子串,并问满足最少删除次数的方案数有多少个
f[i]:[1,i] 必须删除[i-m+1,i] 的子串,总共的最少删除次数
tot[i]:[1,i] 必须删除[i-m+1,i] 的子串,所有满足最少删除次数的方案数
状态转移:f[i] = f[j] + 1;需要删除的情况多了一个
三种情况:
1.子串前缀和后缀不相等,直接删除主串中所有满足条件的子串就可以了,方案数是1
2.子串前缀和后缀相等,这时候会有重叠,f[i] 不能从所有k 属于[i-m+1,i] 的情况中转移过来 。
3.子串前缀和后缀相等,这时候会有重叠, [j,i] 中如果有k 满足 [k-m+1,k] 是子串,并且 k < i && k - m + 1 > j ,f[i] 不能从这些 j 转移过来,因为它们的情况已经记录到 k 里了,如果再转移,总的删除次数会减少
最后答案:
最后一个满足条件的串内,所有最少次数的方案数累计。
//-------------------------代码---------------------------- #define int ll const int N = 3000,mod = 1e9+7; int n,m; int f[N]; int tot[N]; void solve() { V<int>v; ms(f,inf);ms(tot,0); string s,t; cin>>s>>t; n = s.size(),m = t.size(); s = ' ' + s; v.pb(0); for(int i = 1;i + m - 1 <= n;i ++ ) { if(s.substr(i,m) == t) v.pb(i + m - 1); } f[0] = 0,tot[0] = 1; for(int i = 0;i<v.size();i ++ ) { for(int j = i - 1;j >= 0;j -- ) { if(v[i] - v[j] < m) continue; bool flag = 1; for(int k = j + 1; k < i ;k ++ ) { if(v[k] - v[j] >= m && v[i] - v[k] >= m) { flag = 0; } } if(flag == 0) break; if(f[i] > f[j] + 1) { f[i] = f[j] + 1; tot[i] = tot[j]; } else if(f[i] == f[j] + 1) { tot[i] = (tot[i] + tot[j]) % mod; } } } int mi = inf,ans = 0; for(int i = 0; i < v.size();i ++ ) { if(v.back() - v[i] < m) mi = min(mi,f[i]); } for(int i = 0;i < v.size();i ++ ) { if(v.back() - v[i] < m && f[i] == mi) ans = (ans + tot[i]) % mod; } cout<<mi<<' '<<ans<<endl; } void main_init() {} signed main(){ AC();clapping();TLE; cout<<fixed<<setprecision(12); main_init(); // while(cin>>n,n) // while(cin>>n>>m,n,m) int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------
#include<bits/stdc++.h>#define TLE ios::sync_with_stdio(0),cin.tie(0)#define endl "\n"#define FILE "a"#define pb push_back#define gg exit(0);#define rt return;#define bd cout<<"debug"<<endl;#define db(x) cout<<#x<<':'<<x<<endl;#define dbb(i,a) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<endl;#define dbbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;#define TIME cout<<"RuningTime: "<<clock()<<"ms\n";#define YES cout<<"YES"<<endl;#define Yes cout<<"Yes"<<endl;#define NO cout<<"NO"<<endl;#define No cout<<"No"<<endl;#define None cout<<-1<<endl;#define el cout<<endl;#define x first#define y second#define V vector#define fo(i,j,n) for(int i = j;i<=n;i++)#define of(i,n,j) for(int i = n;i>=j;i--)#define fe(i,u) for(int i = h[u];~i;i=ne[i])#define all(a) a.begin(),a.end()#define alll(a) a.begin()+1,a.end()#define ms(a,b) memset(a, b, sizeof(a));#define tr_len(u) (tr[u].r - tr[u].l + 1)#define tr_mid (tr[u].l + tr[u].r >> 1)#define ul (u<<1)#define ur (u<<1|1)#define lowbit(x) (x&-x)#define gcd(a,b) __gcd(a,b)#define CLAP 11243using namespace std;void clapping() {#if CLAP == 1srand(time(NULL)+rand());freopen("a.in","r",stdin);freopen("a.out","w",stdout);//freopen("a.in","w",stdout);#endif}template<class T>inline void read(T &res) { char c;T flag = 1; while((c = getchar()) < '0' || c > '9') if(c == '-') flag = -1;res = c - '0'; while((c=getchar())>='0'&&c<='9')res=(res<<1)+(res<<3)+(c^48);res*=flag;}typedef pair<int,int> pii;typedef pair<long,long>pll;typedef long long ll;const int inf = 0x3f3f3f3f;const ll INF = 0x3f3f3f3f3f3f3f3fll;const double eps = 1e-8;int dy[] = {1,0,-1,0,1,1,-1,-1};int dx[] = {0,1,0,-1,1,-1,1,-1};ll qmi(ll a,ll b) {int res = 1;for(;b;b>>=1,a = a * a ) {if(b&1) res = res * a;}return res;}template<class T> T exgcd(T a,T b,T &x,T &y) {if(b == 0) {x = 1;y = 0;return a;}ll d = gcd_ed(b,a%b,y,x);y = y - a / b * x;return d;}template<class T> T qmul(T a,T b,T p) {T res = 0;for(;b;b >>= 1,a = (a + a) % p) {res = (res + a) % p;}return res;}/*文档区
*/void AC(){ //// _oo0oo_// o8888888o// 88" . "88// (| -_- |)// 0\ = /0// ___/`---'\___// .' \\| |// '.// / \\||| : |||// \// / _||||| -:- |||||- \// | | \\\ - /// | |// | \_| ''\---/'' |_/ |// \ .-\__ '-' ___/-. /// ___'. .' /--.--\ `. .'___// ."" '< `.___\_<|>_/___.' >' "".// | | : `- \`.;`\ _ /`;.`/ - ` : | |// \ \ `_. \_ __\ /__ _/ .-` / /// =====`-.____`.___ \_____/___.-`___.-'=====// 佛祖保佑, 永无bug;}
//-------------------------代码----------------------------
#define int llconst int N = 3000,mod = 1e9+7;int n,m;
int f[N];int tot[N];
void solve(){V<int>v; ms(f,inf);ms(tot,0);string s,t;cin>>s>>t;n = s.size(),m = t.size();s = ' ' + s;v.pb(0);for(int i = 1;i + m - 1 <= n;i ++ ) {if(s.substr(i,m) == t) v.pb(i + m - 1);} f[0] = 0,tot[0] = 1;for(int i = 0;i<v.size();i ++ ) {for(int j = i - 1;j >= 0;j -- ) {if(v[i] - v[j] < m) continue;bool flag = 1;for(int k = j + 1; k < i ;k ++ ) {if(v[k] - v[j] >= m && v[i] - v[k] >= m) {flag = 0;}}if(flag == 0) break;if(f[i] > f[j] + 1) {f[i] = f[j] + 1;tot[i] = tot[j];} else if(f[i] == f[j] + 1) {tot[i] = (tot[i] + tot[j]) % mod;} }}int mi = inf,ans = 0;for(int i = 0; i < v.size();i ++ ) {if(v.back() - v[i] < m) mi = min(mi,f[i]);}for(int i = 0;i < v.size();i ++ ) {if(v.back() - v[i] < m && f[i] == mi) ans = (ans + tot[i]) % mod;} cout<<mi<<' '<<ans<<endl; }void main_init() {}signed main(){AC();clapping();TLE;cout<<fixed<<setprecision(12);main_init();// while(cin>>n,n)// while(cin>>n>>m,n,m)int t;cin>>t;while(t -- )solve();//{solve(); }return 0;}
/*样例区
*/
//------------------------------------------------------------