2017年8月8日提高组T2 呀!回文串

本文介绍了一种算法,用于计算将给定字符串转换为回文串所需的最小代价。通过动态规划方法,针对字符串中每个字符的添加和删除成本进行优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

小B的名字是由前n个小写字母组成的一个长度为m字符串。一天,小B看上了一个金发碧眼的漂亮妹子,但妹子在知道了小B的名字后,就无情地抛弃了小B,而原因竟然是小B的名字不够优美!在小B的追问下,妹子告诉小B,只有回文串是优美的。于是小B决定把自己的名字变得优美,但每加入或删除一个字母都要付出一定的代价。为了小B的人生大事,请你告诉小B他最少需要付出多少代价。

Input

第一行两个数分别表示n和m。
第二行是一个长度为m的字符串,仅由前n个小写字母组成。
接下来n行,每行含有一个字母和两个正整数,表示添加和删除这个字母的费用。

Output

一行一个整数,表示最小费用。

Sample Input

3 4
abbc
a 10 10
b 20 20
c 30 30

Sample Output

40

Hint

【数据规模与约定】
对于前30%的数据,m <= 10
对于前50%的数据,m <=100
对于前100%的数据,n<=26,m<=2000,0<=费用<=10000

分析:对于同一个字母,删去和添加是一样的。设f[i,j]为把i—j变为回文数的代价。有
f[i,j]=min(f[i+1,j]+cost[s[i]],f[i,j-1]+cost[s[j]])
{s[i]<>s[j]}
f[i,j]=f[i+1,j-1] {s[i]=s[j]}

代码:

var
 a:array [1..2001] of longint;
 g:array [1..26,1..2] of longint;
 f:array [0..2001,0..2001] of longint;
 x,y,n,m,i,j,k,l:longint;
 ch:char;

function min(x,y:longint):longint;
 begin
  if x<y then exit(x)
         else exit(y);
 end;

begin
 readln(n,m);
 for i:=1 to m do
  begin
   read(ch);
   a[i]:=ord(ch)-96;
  end;
 readln;
 for i:=1 to n do
  begin
   read(ch);
   readln(g[ord(ch)-96,1],g[ord(ch)-96,2]);
  end;
 for k:=2 to m do
  for i:=1 to m-k+1 do
   begin
    j:=i+k-1;
    f[i,j]:=maxlongint;
    if a[i]=a[j] then f[i,j]:=min(f[i,j],f[i+1,j-1])
    else
     begin
      f[i,j]:=min(f[i,j],f[i+1,j]+min(g[a[i],2],g[a[i],1]));
      f[i,j]:=min(f[i,j],f[i,j-1]+min(g[a[j],2],g[a[j],1]));
     end;
   end;
 writeln(f[1,m]);
end.


以下是一个MIPS汇编程序,用于检查输入的字符串是否为回文串: ``` .data prompt: .asciiz "Enter string: " # 提示用户输入字符串 output: .asciiz "The string is a palindrome." # 字符串为回文串的输出消息 not_palindrome: .asciiz "The string is not a palindrome." # 字符串不为回文串的输出消息 str: .space 80 # 用于存储输入的字符串,最大长度为 80 .text .globl main main: # 输出提示消息 li $v0, 4 la $a0, prompt syscall # 读入字符串 li $v0, 8 la $a0, str li $a1, 80 syscall # 计算字符串长度 move $t0, $a0 # 将字符串首地址保存到 $t0 中 li $t1, 0 # 计数器清零 loop: lb $t2, ($t0) # 读取一个字符 beqz $t2, check_palindrome # 如果读到了字符串结尾,跳转到检查回文串的代码 addi $t0, $t0, 1 # 字符串指针加 1 addi $t1, $t1, 1 # 计数器加 1 j loop check_palindrome: subi $t0, $t0, 1 # 将字符串指针指向最后一个字符 li $t2, 0 # 初始化计数器 div $t1, 2 # 计算字符串长度的一半 mflo $t3 # 将商保存到 $t3 中 loop2: lb $t4, ($a0) # 读取一个字符 lb $t5, ($t0) # 从字符串末尾读取一个字符 bne $t4, $t5, not_palindrome # 如果两个字符不相等,跳转到输出不是回文串的代码 addi $a0, $a0, 1 # 字符串指针加 1 subi $t0, $t0, 1 # 从字符串末尾往前移动一个字符 addi $t2, $t2, 1 # 计数器加 1 bne $t2, $t3, loop2 # 如果还没有遍历完整个字符串,跳转到 loop2 # 如果程序能够执行到这里,说明字符串是回文串 li $v0, 4 la $a0, output syscall j end not_palindrome: li $v0, 4 la $a0, not_palindrome syscall end: li $v0, 10 syscall ``` 该程序首先提示用户输入字符串,然后读取字符串。程序接着计算字符串长度,并将字符串指针移动到最后一个字符的位置。然后,程序使用循环比较字符串的首尾字符是否相等,如果相等,则将指针向后移动一个字符,向前移动一个字符,直到遍历整个字符串或者发现首尾字符不相等。如果整个字符串都被遍历了,并且字符串中的所有字符都相等,则说明该字符串是回文串,程序输出相应的消息。如果发现首尾字符不相等,则说明该字符串不是回文串,程序输出相应的消息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值