[SDOI2014] recuento - autómata AC, dp digitales

Dada una longitud \ (L \) de un gran número \ (n- \) , en busca de \ (\ leq n \) no contiene una sub-secuencia de la forma dada \ (m \) el número contado del diccionario. \ (L \ leq 1,200, m \ leq 100, \ sum len \ leq 1500 \)

Solución

Set \ (f [i] [j ] [0/1] \) representa el avance considerado \ (I \) bits, ir \ (J \) nodo, un carácter siguiente es limitado en el siguiente número de programa

métodos de transferencia

  • \ (F [i-1] [j] [0] \ a f [i] [ch [j] [0..9]] [0] \)
  • \ (F [i-1] [j] [1] \ a f [i] [ch [j] [0..s [i] -1]] [0] \)
  • \ (F [i-1] [j] [1] \ a f [i] [ch [j] [s [i]]] [1] \)

Pero teniendo en cuenta los números que no podemos tener ceros a la izquierda, pero puede que tengamos diccionarios

Se dice que sólo los fuertes de eliminación \ (ch [0] [0 ] \) puede resolver el problema (niebla)

#include <bits/stdc++.h>
using namespace std;

const int N = 5005;
const int mod = 1e+9 + 7;
#define ch c
queue <int> q;
int n,m,c[N][10],f[N][N][2],val[N],fi[N],cnt,ans[1005];

void ins(char *str,int id) {
    int len=strlen(str), p=0;
    for(int i=0; i<len; i++) {
        int v=str[i]-'0';
        if(!c[p][v]) c[p][v]=++cnt;
        p=c[p][v];
    }
    val[p]=id;
}
void build() {
    for(int i=0; i<10; i++) if(c[0][i]) fi[c[0][i]]=0, q.push(c[0][i]);
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=0; i<10; i++)
            if(c[u][i]) fi[c[u][i]]=c[fi[u]][i], q.push(c[u][i]);
            else c[u][i]=c[fi[u]][i];
    }
}

char str[N],pat[N];

void sh(int &x,int y) {
    x=(x+y)%mod;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>str;
    n=strlen(str);
    cin>>m;
    for(int i=1;i<=m;i++) {
        cin>>pat;
        ins(pat,i);
    }
    build();
    ch[0][0]=0;
    for(int i=1;i<str[0]-'0';i++) sh(f[1][ch[0][i]][0],1);
    sh(f[1][ch[0][str[0]-'0']][1],1);
    for(int i=2;i<=n;i++) {
        for(int j=1;j<10;j++) sh(f[i][ch[0][j]][0],1);
        for(int j=0;j<=cnt;j++) if(val[j]==0) {
            for(int k=0;k<=9;k++) {
                if(val[ch[j][k]]==0) sh(f[i][ch[j][k]][0],f[i-1][j][0]);
            }
            for(int k=0;k<str[i-1]-'0';k++) {
                if(val[ch[j][k]]==0) sh(f[i][ch[j][k]][0],f[i-1][j][1]);
            }
            if(val[ch[j][str[i-1]-'0']]==0)
                sh(f[i][ch[j][str[i-1]-'0']][1],f[i-1][j][1]);
        }
    }
    int ans=0;
    for(int i=0;i<=cnt;i++) if(val[i]==0) sh(ans,f[n][i][0]+f[n][i][1]);
    cout<<ans;
}

Supongo que te gusta

Origin www.cnblogs.com/mollnn/p/12453627.html
Recomendado
Clasificación