[PKU/POJ][3691][DNA repair][AC自动机+DP]

本文介绍了一种使用AC自动机构建确定有限自动机(DFA)的方法,用于计算给定字符串与一系列病毒串之间的最小编辑距离。通过动态规划算法,在DFA的状态转移过程中寻找最优解。

先用AC自动机构建一个不含有任何病毒串的 DFA , dp[i][j] 表示到目标串的第 i 个字符,DFA 状态为 j 时的最小修改数量。则 dp[i][ son[j] ]= min{ dp[i][ son[j] ], dp[i-1][j]+ (tran[j][ son[j] ]!= str[i] ) }  tran[j][ son[j] ]表示从 j 到 son[j] 经过的字母边。

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define min(a,b) ((a)<(b)?(a):(b))
#define inf 0x7fffffff

int const N= 2000;
struct Node{
	int next[4];
	int fail, flag;
	void init(){
		for( int i= 0; i< 4; ++i ) next[i]= 0;
		fail= -1; flag= 0;
	}
}tb[N];

char str[N];
int dp[N][N], n, cnt;

int inline toInt( char ch ){
	if( ch== 'A' ) return 0;
	if( ch== 'T' ) return 1;
	if( ch== 'G' ) return 2;
	if( ch== 'C' ) return 3;
}

void insert( char*s ){
	int rt= 0;
	while( *s ){
		int t= toInt( *s );
		
		if( tb[rt].next[t]== 0 ){
			tb[++cnt].init();
			tb[rt].next[t]= cnt;
		}
		rt= tb[rt].next[t]; s++;
	}
	tb[rt].flag= 1;
}

int que[N], head, tail;
void bfs(){
	int p, q, now;
	head= 0, tail= 0, que[0]= 0;
	
	while( head<= tail ){
		now= que[head++];
		
		for( int t= 0; t< 4; ++t )
		if( tb[now].next[t] ){
			p= tb[now].next[t]; q= tb[now].fail;
			while( q!= -1 && !tb[q].next[t] ) q= tb[q].fail;
			if( q== -1 ) tb[p].fail= 0;
			else{
				tb[p].fail= tb[q].next[t];
				tb[p].flag|= tb[ tb[p].fail ].flag;
			}
			que[++tail]= p;
		}
		else{
			q= tb[now].fail;
			while( q!= -1 && !tb[q].next[t] ) q= tb[q].fail;
			if( q== -1 ) tb[now].next[t]= 0;
			else tb[now].next[t]= tb[q].next[t];
		}
	}
}

int main(){
	int test= 1;
	while( scanf("%d",&n)!= EOF ){
		if( n== 0 ) return 0;
		cnt= 0; tb[0].init();
		
		for( int i= 0; i< n; ++i ){
			scanf("%s", str );
			insert( str );
		}
		bfs();
		
		scanf("%s",str);
		int len= strlen(str);
		for( int i= 0; i<= len; ++i )
		for( int j= 0; j<= cnt; ++j ) dp[i][j]= inf;
		dp[0][0]= 0;
		
		for( int i= 1; i<= len; ++i ){
			for( int j= 0; j<= cnt; ++j )
			if( dp[i-1][j]!= inf && !tb[j].flag ){
				for( int t= 0; t< 4; ++t )
				if( !tb[ tb[j].next[t] ].flag ){
					int k= tb[j].next[t];
					
					dp[i][k]= min( dp[i][k], dp[i-1][j]+ ( t!= toInt( str[i-1] ) ) );
				}
			}
		}
		
		int ans= inf;
		for( int i= 0; i<= cnt; ++i ) ans= min( ans, dp[len][i] );
		
		printf("Case %d: ", test++ );
		if( ans== inf ) printf("-1\n");
		else printf("%d\n", ans );
	}
	
	return 0;
}
 

 

独立储能的现货电能量与调频辅助服务市场出清协调机制(Matlab代码实现)内容概要:本文围绕“独立储能的现货电能量与调频辅助服务市场出清协调机制”展开,提出了一种基于Matlab代码实现的优化模型,旨在协调独立储能系统在电力现货市场与调频辅助服务市场中的联合出清问题。文中结合鲁棒优化、大M法和C&CG算法处理不确定性因素,构建了多市场耦合的双层或两阶段优化框架,实现了储能资源在能量市场和辅助服务市场间的最优分配。研究涵盖了市场出清机制设计、储能运行策略建模、不确定性建模及求解算法实现,并通过Matlab仿真验证了所提方法的有效性和经济性。; 适合人群:具备一定电力系统基础知识和Matlab编程能力的研究生、科研人员及从事电力市场、储能调度相关工作的工程技术人员。; 使用场景及目标:①用于研究独立储能在多电力市场环境下的协同优化运行机制;②支撑电力市场机制设计、储能参与市场的竞价策略分析及政策仿真;③为学术论文复现、课题研究和技术开发提供可运行的代码参考。; 阅读建议:建议读者结合文档中提供的Matlab代码与算法原理同步学习,重点关注模型构建逻辑、不确定性处理方式及C&CG算法的具体实现步骤,宜在掌握基础优化理论的前提下进行深入研读与仿真调试。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值