hdu2457 AC 로봇 + DP
3598 단어 Baoge
그 다음은 동적 기획의 과정이다.pp[i][j]는 앞의 i 문자가trie에 있는 j 노드 상태에 도달하기 위해 변경해야 하는 최소 개수를 대표하고 이에 따라 뒤로 미루어 다음 문자가 무엇인지 열거하고 ac자동기에서 상태가 이동한다.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#define maxn 1<<29
using namespace std;
int ch[1111][4],val[1111];
int f[1111];
int sz,n,m;
char str[22];
char s[1111];
int dp[1111][1111];
int ans;
void init()
{
sz=0;
memset(ch[0],0,sizeof(ch[0]));
}
int getnum(char c)
{
switch(c)
{
case 'A':
return 0;
case 'C':
return 1;
case 'G':
return 2;
case 'T':
return 3;
}
}
void insert(char *a,int vv)
{
int u=0,l=strlen(a);
for(int i=0; i<l; i++)
{
int c=getnum(a[i]);
if(!ch[u][c])
{
ch[u][c]=++sz;
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
}
u=ch[u][c];
}
val[u]=vv;
}
void getfail()
{
queue<int>q;
f[0]=0;
for(int i=0; i<4; i++)
{
int u=ch[0][i];
if(u)
{
f[u]=0;
q.push(u);
}
}
while(!q.empty())
{
int r=q.front();
q.pop();
for(int i=0; i<4; i++)
{
int u=ch[r][i];
if(!u)continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][i])v=f[v];
f[u]=ch[v][i];
if(val[f[u]])val[u]=val[f[u]];
}
}
}
void solve()
{
int l=strlen(s);
for(int i=0; i<=l; i++)
{
for(int j=0; j<=sz; j++)dp[i][j]=maxn;
}
dp[0][0]=0;
for(int i=0; i<l; i++)
{
for(int j=0; j<=sz; j++)
{
if(val[j]||dp[i][j]==maxn)continue;
for(int k=0; k<4; k++)
{
int u=ch[j][k];
if(u)
{
if(val[u])continue;
else
{
if(getnum(s[i])==k)dp[i+1][u]=min(dp[i][j],dp[i+1][u]);
else dp[i+1][u]=min(dp[i][j]+1,dp[i+1][u]);
}
}
else
{
int r=j;
while(r&&!ch[r][k])r=f[r];
int v=ch[r][k];
if(v)
{
if(!val[v])
{
if(getnum(s[i])==k)dp[i+1][v]=min(dp[i][j],dp[i+1][v]);
else dp[i+1][v]=min(dp[i][j]+1,dp[i+1][v]);
}
}
else
{
if(getnum(s[i])==k)dp[i+1][v]=min(dp[i][j],dp[i+1][v]);
else dp[i+1][v]=min(dp[i][j]+1,dp[i+1][v]);
}
}
}
}
}
for(int i=0;i<=sz;i++)ans=min(ans,dp[l][i]);
}
int main()
{
int ca=1;
while(scanf("%d",&n)&&n)
{
init();
for(int i=0; i<n; i++)
{
scanf("%s",str);
insert(str,1);
}
getfail();
scanf("%s",s);
ans=maxn;
solve();
printf("Case %d: ",ca++);
if(ans==maxn)printf("-1
");
else printf("%d
",ans);
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
HDUOJ 4632 2013 멀티 스쿨 4차전 1문제전송문 제목: 문자열의 회문 서열의 개수를 구하십시오. 임의의 회문 서열의 끝을 맺는 두 문자가 반드시 같다는 것을 알아차리면 구간 dp를 표시하고 dp[i][j]로 원 문자열의 [i, j] 위치에 나타난 회문 서열...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.