codeforces176D——Hyper String

来源:互联网 发布:淘宝台湾入台证办理 编辑:程序博客网 时间:2024/05/17 05:49

1、题意:给一些字符串,总长度小于106,给你一个由这些字符串中的某些组成(可重复)的字符串b,再给你一个长度小于2000的字符串a,求最长公共子序列。
2、分析:首先既然最长公共子序列,考虑dp,fi,j表示比配到a中的第i个字符,现在的公共序列长度是j,在b中能满足的最小位置,答案显然为这个第二维对吧,本质就是把朴素的最长公共子序列状态转变一下。fi,j=min(fi1,j,calc(fi1,j1,a[i]))calc函数用来计算在b中满足最小位置,方程列出来了,然而朴素的当然会TLE,我们需要预处理某个字符后的第一个某字符在哪里,具体看代码,我实现的有些啰嗦,可以去看看立陶宛的krk的代码,简洁明了。

#include <map>#include <set>#include <cmath>#include <queue>#include <vector>#include <bitset>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define M 1000010#define LL long long#define MOD 1000000007#define inf 2147483647#define llinf 4000000000000000000ll#define For(i, x, y) for(int i = (x); i < (y); i ++)#define rep(i, x, y) for(int i = (x); i <= (y); i ++)#define drep(i, x, y) for(int i = (x); i >= (y); i --)inline int read(){    char ch=getchar();int x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline LL llread(){    char ch=getchar();LL x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}//pair<int , int> Next[2010][26];int nxt[M][26];string str[2010];int id[2010], sum[2010];int head[26];pair<int , int> f[2010][2010];inline pair<int , int> calculate(pair<int , int> now, int latin){    bool flag = false;    if(now.first == 1 && now.first == 1) flag = true;    if(now.first == inf || now.second == inf) return make_pair(inf, inf);    pair<int , int> ret = make_pair(now.first, 0);    if(now.second != str[id[now.first]].size()){        //cout << "fuck" << endl;        int t = nxt[sum[id[now.first] - 1] + now.second + 1][latin];        if(t != -1) ret.second = t;        else ret = Next[now.first + 1][latin];    }    else ret = Next[now.first + 1][latin];    if(ret.first == -1 || ret.second == -1) ret = make_pair(inf, inf);    return ret;}inline void solve(){    string st; cin >> st;    int len = st.size();    For(i, 0, 2010) For(j, 0, 2010) f[i][j] = make_pair(inf, inf);    f[0][0] = make_pair(0, 0);    int ans = 0;    rep(i, 1, len){        rep(j, 0, i){            if(j) f[i][j] = min(f[i - 1][j], calculate(f[i - 1][j - 1], st[i - 1] - 'a'));            else f[i][j] = f[i - 1][j];            if(f[i][j] != f[2005][2005]) ans = max(ans, j);            /*if(f[i][j] != f[2005][2005]){                if(j == 2){                    printf("%d %d %d %d\n", i, j, f[i - 1][j - 1].first, f[i - 1][j - 1].second);                }            }*/        }    }    cout << ans << endl;    return; }int main(){    //freopen("0input.in", "r", stdin);    int n = read();    rep(i, 1, n) cin >> str[i];    int m = read();    rep(i, 1, m) id[i] = read();    memset(nxt, -1, sizeof(nxt));    For(i, 0, 2010) For(j, 0, 26) Next[i][j] = make_pair(-1, -1);    rep(i, 1, n){        sum[i] = sum[i - 1] + str[i].size();        memset(head, 0, sizeof(head));        For(j, 0, str[i].size()){            //if(head[str[i][j] - 'a'] != -1){                if(!head[str[i][j] - 'a']) head[str[i][j] - 'a'] = sum[i - 1];                rep(kt, head[str[i][j] - 'a'] + 1, sum[i - 1] + j + 1){                    nxt[kt][str[i][j] - 'a'] = j + 1;                }                head[str[i][j] - 'a'] = sum[i - 1] + j + 1;            //}         }    }    drep(i, m, 1){        rep(j, 0, 25){            if(nxt[sum[id[i] - 1] + 1][j] != -1) Next[i][j] = make_pair(i, nxt[sum[id[i] - 1] + 1][j]);            else Next[i][j] = Next[i + 1][j];        }    }    //cout << Next[1][0].first << endl << Next[2][0].first;    solve();    return 0;}
0 0
原创粉丝点击