HOJ 13108 Just Another Knapsack Problem (AC自动机+dp)

来源:互联网 发布:node.js query 编辑:程序博客网 时间:2024/05/22 12:15

这套题是我们学长出的,质量都很高。不过我们OJ真的是太卡时间了。。

题意很简单,给一个目标串,以及很多模板串,每个模板串都有个value,可以重复用,问拼成目标串得到的最大value是多少。

学长的题解没有用AC自动机。貌似是说dp加字典树转移。没仔细看。不过这道题很明显的AC自动机啊。

模板串构建完AC自动机后,把目标串放进去find一下,用dp[i]代表1到i都被拼完所能得到的最大value,如果找到一个单词节点,如果dp[i - len]不是0且不是起始点(len是这个找到单词的长度)那么就不能转移,反之就dp[i] = max(dp[i] , dp[i-len] + val[j])。

由于没说模板串会不会有重复,所以我用map判了一下,如果下一个加进来的在map里有,且val比map里的大,那么就更新,不然就不更新。结果无限超时。。然后想到一个优化办法,不用map,直接加,加到最后如果val[u] 已经有值了并且那个val小于新加进来的,那么就更新。这才1.5s过了。。

AC代码:

//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<ctype.h>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdlib>#include<stack>#include<cmath>#include<queue>#include<set>#include<map>#include<ctime>#include<string.h>#include<string>#include<sstream>#include<bitset>using namespace std;#define ll __int64#define ull unsigned long long#define eps 1e-8#define NMAX 1000000005#define MOD 1000000007#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1#define PI acos(-1)template<class T>inline void scan_d(T &ret){    char c;    int flag = 0;    ret=0;    while(((c=getchar())<'0'||c>'9')&&c!='-');    if(c == '-')    {        flag = 1;        c = getchar();    }    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();    if(flag) ret = -ret;}ll dp[100005];int len[1005],v[1005];char T[100005];//map<string,int>mp;struct AhoCorasick{    int ch[1000*305][26];    int val[1000*305],last[1000*305],f[1000*305];    int sz;    void init(){sz = 1; memset(ch[0],0,sizeof(ch[0]));}    int idx(char c){return c-'a';}    void insert(char *s, int va)    {        int u = 0, n = strlen(s);        for(int i = 0; i < n; i++)        {            int c = idx(s[i]);            if(!ch[u][c])            {                memset(ch[sz],0,sizeof(ch[sz]));                val[sz] = 0;                ch[u][c] = sz++;            }            u = ch[u][c];        }        if(val[u] && v[va] < v[val[u]]) return;        val[u] = va;    }    void getfail()    {        queue<int>q;        f[0] = 0;        for(int c = 0; c < 26; c++)        {            int u = ch[0][c];            if(u){f[u] = 0; q.push(u); last[u] = 0;}        }        while(!q.empty())        {            int r = q.front(); q.pop();            for(int c = 0; c < 26; c++)            {                int u = ch[r][c];                if(!u)                {                    ch[r][c] = ch[f[r]][c];                    continue;                }                q.push(u);                int v = f[r];                while(v && !ch[v][c]) v = f[v];                f[u] = ch[v][c];                last[u] = val[f[u]] ? f[u] : last[f[u]];            }        }    }    void find(char *T)    {        int n = strlen(T);        int j = 0;        for(int i = 0; i < n; i++)        {            int c = idx(T[i]);            j = ch[j][c];            if(val[j]) print(i,j);            else if(last[j]) print(i,last[j]);        }    }    void print(int pos ,int j)    {        if(j)        {            int p = val[j];            if(dp[pos+1-len[p]] != -1)                dp[pos+1] = max(dp[pos+1],dp[pos+1-len[p]]+(ll)v[p]);            print(pos,last[j]);        }    }};AhoCorasick ac;int main(){#ifdef GLQ//    freopen("input.txt","r",stdin);    freopen("o1.txt","w",stdout);#endif // GLQ    int n;    while(gets(T))    {        ac.init();        scan_d(n);//        mp.clear();        int lo = strlen(T);        dp[0] = 0;        for(int i = 1; i <= lo; i++)            dp[i] = -1;        char tmp[305];        for(int i = 1; i <= n; i++)        {            int ha;            scanf("%s",tmp);            scan_d(ha);//            if(mp.count(string(tmp)) && v[mp[string(tmp)]] > ha) continue;//            mp[string(tmp)] = i;            v[i] = ha;            len[i] = strlen(tmp);            ac.insert(tmp,i);        }        ac.getfail();        ac.find(T);        if(dp[lo] == -1) printf("0\n");        else printf("%I64d\n",dp[lo]);    }    return 0;}


0 0
原创粉丝点击