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;}
/*样例区

*/
//------------------------------------------------------------



posted @ 2022-09-14 23:21  er007  阅读(91)  评论(0编辑  收藏  举报