列表

详情


NC20149. [JLOI2016]字符串覆盖

描述

字符串A有N个子串B1,B2,…,Bn。如果将这n个子串分别放在恰好一个它在A中出现的位置上(子串之间可以重叠) 这样A中的若干字符就被这N个子串覆盖了。
问A中能被覆盖字符个数的最小值和最大值。

输入描述

第一行包含一个正整数T,表示数据组数。保证T ≤ 10。
接下来依次描述T组数据,每组数据中:
第一行包含一个由小写字母组成的字符串,表示母串A。
第二行包含一个整数N,表示子串的个数。
接下来N行,每行包含一个由小写字母组成的字符串,描述子串。
数据保证所有子串均在母串中出现。字符串长度A ≤ 10000,N ≤ 4,子串长充 ≤ 1000

输出描述

输出为T行,对应每组数据的答案。每行包含两个整数Minans和Maxans,分别表示对应数据中能被覆盖字符数量的最小值和最大值。

示例1

输入:

2 
hello 
4 
he 
l 
l 
o 
abacaba 
4 
ab 
ba 
a 
c

输出:

4 5
4 6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 15ms, 内存消耗: 2112K, 提交时间: 2022-12-11 14:45:17

#include<iostream>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<iomanip>
#include<stack>
#include<cmath>


using namespace std;

#define Cpp11

#ifdef Cpp11
    #define _for(i,a,b) for(auto i = (a);i<(b);++i)
    #define _rep(i,a,b) for(auto i = (a);i<=(b);++i)
    #define _dep(i,a,b) for(auto i = (a);i>=(b);--i)
    #include<ctime>
    #include<complex>
    #include<random>
    #include<chrono>
    #include<limits>
    #include<complex>
    #include<unordered_set>
    #include<unordered_map>
    #include<cassert>
    #include<functional>
    #include<bitset>
    #define IO ios::sync_with_stdio(0);cout.tie(0);cin.tie(0);
#endif

#ifndef Cpp11
    #define _for(i,a,b) for(int i = (a);i<(b);++i)
    #define _rep(i,a,b) for(int i = (a);i<=(b);++i)
    #define _dep(i,a,b) for(int i = (a);i>=(b);--i)
    #define IO ios::sync_with_stdio(false);cout.tie(NULL);cin.tie(NULL);
#endif


using namespace std;



#define fr first
#define sc second
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define pob pop_back
#define pf push_front
#define pof pop_front
#define sci(x) scanf("%d",&(x))
#define scl(x) scanf("%lld",&(x))
#define debugline fprintf(stderr,"-----------------------\n");
#define szint(x) ((int)(x).size())



#ifdef I128IO
typedef __int128 I128;
char buff[200];
template<typename T>
void read(T& o)
{
    o = 0;
    scanf("%s",buff);
    //printf("%s\n",buff);
    T f = 1;
    int i = 0;

    if(buff[0]=='-')i++,f = -1;
    for(;buff[i];++i)
    {
        o*=10,o+=buff[i]-'0';
    }
    o*=f;
}

template<typename T>
void write(T o)
{
    int len = 0;
    buff[0] = '0';
    if(o==0)
    {
        putchar('0');
        return;
    }
    int f = 1;
    if(o<0) f = -1;
    o*=f;
    for(;o;o/=10) buff[len++] = o%10+'0';
    if(f==-1) buff[len++] = '-';
    reverse(buff,buff+len);
    buff[len++] ='\0';
    printf("%s",buff);
}
#endif

#ifdef FIO
char buff[100];
template<typename T>
void read(T& o)
{
    o = 0;
    scanf("%s",buff);
    //printf("%s\n",buff);
    T f = 1;
    int i = 0;
    if(buff[0]=='-')i++,f = -1;
    for(;buff[i];++i)
    {
        o*=10,o+=buff[i]-'0';
    }
    o*=f;
}
template<typename T>
void write(T o)
{
    int len = 0;
    buff[0] = '0';
    if(o==0)
    {
        putchar('0');
        return;
    }
    int f = 1;
    if(o<0) f = -1;
    o*=f;
    for(;o;o/=10) buff[len++] = o%10+'0';
    if(f==-1) buff[len++] = '-';
    reverse(buff,buff+len);
    buff[len++] ='\0';
    printf("%s",buff);
}
#endif

#define _Random_


#ifdef _Random_
    mt19937 __MT(chrono::system_clock::now().time_since_epoch().count());
#endif

#ifndef BigNumber
    typedef unsigned long long uLL;
    typedef long long LL;
    typedef pair<LL,LL> pLL;
    typedef vector<LL> vL;
    typedef vector<vL> vLL;
#endif

#ifdef I128IO
    typedef __int128 SPLL;
    typedef vector<SPLL> vSPLL;
#endif

typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<vii> viii;
typedef vector<viii> viiii;
typedef pair<int,int> pii;

#ifdef Cpp11
    typedef complex<double> CD;
#endif


const int maxn = 10000+10;
const LL maxm = 4;
const int apsz = 26;
const int inf = 1e9;
const int block = 100;

char A[maxn];
int n,m,S;
int f[maxn];
int has[maxm][maxn];
vi canpos[maxm];
char s[maxm][maxn];
int Len[maxm];
int maxval,minval;
deque<int> q[1<<4];
int pre[maxn][1<<4];
int dp[maxn][1<<4];

void dfs(int d,int preneed,int preend,int tot,vi& vis)
{
    //cerr<<d<<" "<<preneed<<" "<<preend<<endl;
    if(d==m)
    {
        maxval = max(maxval,tot);

        return;
    }
    int alltot = tot;
    _for(i,0,m)
    {
        if(vis[i])continue;
        alltot = tot;
        if(preneed==0)
        {
            int pt = upper_bound(all(canpos[i]),preend)-canpos[i].begin();
            if(pt!=szint(canpos[i]))
            {
                vis[i] = 1;
                int nowend = canpos[i][pt]+Len[i]-1;
                alltot+=Len[i];
                //cerr<<nowend<<endl;
                dfs(d+1,0,nowend,alltot,vis);
                dfs(d+1,1,nowend,alltot,vis);
                vis[i] = 0;
            }
        }
        else
        {
            int pt = lower_bound(all(canpos[i]),preend)-canpos[i].begin();

            if(pt>0||canpos[i][pt]==preend)
            {
                if(canpos[i][pt]!=preend)--pt;
                int nowend = canpos[i][pt]+Len[i]-1;
                alltot = tot+max(nowend-preend,0);
                vis[i] = 1;
                dfs(d+1,0,max(nowend,preend),alltot,vis);
                dfs(d+1,1,max(nowend,preend),alltot,vis);
                vis[i] = 0;
            }
        }
    }
}

inline void getFail(char* s,int* f,int len)
{
    memset(f,0,sizeof(f));
    f[0] = 0;
    f[1] = 0;
    for(int i = 1;i<len;++i)
    {
        int j = f[i];
        while(j&&s[j]!=s[i])j = f[j];
        f[i+1] = s[j]==s[i]?j+1:j;
    }
}

inline void match(char* s,char* t,int n,int m,int* f,int* pos)
{
    int j = 0;
    _for(i,0,n)
    {
        while(j&&t[j]!=s[i])j = f[j];
        if(t[j]==s[i])++j;
        if(j==m) pos[i] = 1;
    }
}




inline void init()
{
    _for(i,0,m)
    {
        canpos[i].clear();
        getFail(s[i],f,Len[i]);
        _for(j,0,n)has[i][j] = 0;
        match(A,s[i],n,Len[i],f,has[i]);
        _for(j,0,n)
        {
            if(has[i][j])canpos[i].pb(j-Len[i]+1); 
        }
        // _for(j,0,n)
        // {
        //     cerr<<has[i][j]<<" ";
        // }
        // cerr<<endl;
    }
}




inline int cover(int i,int j)
{
    if(Len[i]>Len[j])return 0;
    string ss,ts;
    ss = string(s[i]);
    ts = string(s[j]);
    if(ts.find(ss)!=string::npos)return 1;
    return 0;
}


inline void solve()
{
    init();
    vi vis(m,0);
    dfs(0,0,-1,0,vis);
    S = 1<<m;S--;
    //cerr<<S<<endl;
    _for(i,0,S) q[i].clear();
    _for(j,0,m)
    {
        if((S&(1<<j))==0)continue;
        _for(i,0,m)
        {
            if(i==j)continue;
            if((S&(1<<i))==0)continue;
            if(cover(i,j))S^=(1<<i);
        }
    }
    //cerr<<S<<endl;
    _for(i,0,n)
    {
        _for(j,0,1<<m) 
        {
            if(j)pre[i][j] = dp[i][j] = inf;
            else pre[i][j] = dp[i][j] = 0;
        }
    }
    minval = inf;
    _for(i,0,n)
    {
        if(i)
        {
            _for(x,0,1<<m)pre[i][x] = pre[i-1][x];
        }
        for(int x = 0;x<(1<<m);++x)
        {
            int res = x&S;
            if(res!=x)continue;
            _for(j,0,m)
            {
                if((x&(1<<j))&&has[j][i]==1)
                {
                    if(((1<<j)&x)==0)continue;
                    int y = x^(1<<j);
                    //cerr<<i<<" "<<j<<endl;
                    //cerr<<x<<" "<<y<<endl;
                    int preval;
                    if(i-Len[j]<0)
                    {
                        if(y==0) preval = 0;
                        else preval = inf;
                    }
                    else preval = pre[i-Len[j]][y];
                    //cerr<<i-Len[j]<<" "<<j<<" "<<y<<" "<<preval<<endl;
                    dp[i][x] = min(dp[i][x],preval+Len[j]);
                    for(;!q[y].empty()&&q[y].front()<=i-Len[j];)q[y].pop_front();
                    if(!q[y].empty())
                    {
                        dp[i][x] = min(dp[i][x],dp[q[y].front()][y]-q[y].front()+i);
                        //cerr<<i<<" "<<dp[i][x]<<endl;
                    }
                    for(;!q[x].empty()&&dp[q[x].back()][x]-q[x].back()>=dp[i][x]-i;)
                    {
                        q[x].pop_back();
                    }
                    q[x].pb(i);
                    if(i)pre[i][x] = min(pre[i-1][x],dp[i][x]);
                    else pre[i][x] = dp[i][x];
                }
            }
        }
    }
    minval = pre[n-1][S];
    assert(minval<inf);
    printf("%d %d\n",minval,maxval);
}



int main(void)
{
    int T;
    sci(T);
    for(;T--;)
    {
        scanf("%s",A);
        n = strlen(A);
        sci(m);
        _for(i,0,m)
        {
            scanf("%s",s[i]);
            Len[i] = strlen(s[i]);
        }
        maxval = 0;
        //cerr<<A<<endl;
        solve();
    }
    return 0;
}

上一题