实现题3-17 字符距离问题

实验名称
实现题3-17 字符距离问题。

实验目的
实现题3-17 字符距离问题。

实验原理
使用动态规划算法,根据不同的输入用例,能准确的输出用例中的最短扩展距离,并计算出程序运行所需要的时间。
假设串A1,B1具有最短距离,那么A1[0],B1[0]只有如下三种情况:
Case 1 Case 2 Case 3
A A1[0] ____ A1[0]
B ____ B1[0] B1[0]
每种情况我们需要求出后继子串的最短距离加上当前字符的距离,就得倒最短距离。

实验步骤
① 数据初始化,输入两个字符串以及定值k,设字符串A和B的字串A[1…i]和B[1…j]的扩展距离是val(i, j);
② 依题意,字符串A和B有三种可能的情况:
1)i 和空格匹配。则val(i, j) = val(i-1, j) + k;
2)j 和空格匹配。则val(i, j) = val(i, j-1) + k;
3)扩展距离val(i-1,j-1)加上 i,j 的字符距离。则val(i, j) = val(i-1, j-1) + dist(ai , bi);
由上可知,val(i, j)具有最优子结构性质,且满足如下递推式:
val(i, j) = min{ val(i-1, j) + k,val(i, j-1) + k,val(i-1, j-1) + dist(ai , bi) }

时间复杂度分析
从动态规划递归式可知,算法的时间复杂度为O(mn),m和n分别是字符串A和B的长度。

实验心得
通过这次实验,我巩固了动态规划算法的知识。

#include <iostream>
#include <fstream>
#include <string> 
#include <cmath>
#include <ctime>
using namespace std;
#define MAX 100000    //标识最大的可能整数
int val[300][300];    //用来存储中间值  
string strA;        //字符串A
string strB;       //字符串B
int k;        //定值k
//返回字符a与b的ASCII码的差的绝对值
int dist(char a, char b)
{
	return abs(a-b);     
}
int comp()
{
	val[0][0] = 0;
	int tmp;
    int len1 = strA.length();
    int len2 = strB.length();
        
        for(int i=0; i<=len1; i++)     //字符串A和B的有效下标是1~len 
            for(int j=0; j<=len2; j++)   //i或j是0表示A或B串为空串
            {
                if(i+j)//i和j至少一个大于0
                {
                    val[i][j] = MAX;        //初始化值   
					 
                    tmp = val[i-1][j] + k;    //情况1)  
                    if(i && (tmp<val[i][j]))  //i大于0
                        val[i][j] = tmp;                                              
                        
                    tmp = val[i][j-1]+k;      //情况2)  
                    if(j && (tmp<val[i][j]))  //j大于0
                    	val[i][j] = tmp;				             
                    	
                    tmp = val[i-1][j-1] + dist(strA[i], strB[j]); //情况3)             
                    if((i*j) && (tmp<val[i][j])) //i和j不为0 
                    	val[i][j] = tmp;    
                }
            }
        return val[len1][len2];
}
int main()
{
    ifstream f("input.txt");
    f>>strA>>strB>>k;
    f.close();
    strA = " " + strA;     //此处在字符串开头添加一个空格,是为了使字符串str
    strB = " " + strB;    //输入的有效字符下标从1到str.length()
    clock_t start,end;
    start=clock();
    cout<<comp()<<endl;
    end=clock();
    printf("时间:%fms\n",(double)(end-start)/CLK_TCK);
    return 0;
}
#include<stdlib.h>
#include<time.h>
#include<fstream>
#include<iostream>
using namespace std;
int main()
{
	int n,m;
	cin>>n;
	m=n;
	ofstream out("input.txt");
	srand((unsigned)time(NULL));
	n=n+rand()%10;
	for(int i=0;i<n;i++)
	{
		char x='a'+rand()%26;
		out<<x;
	}
	out<<'\n';
	m=m+rand()%10;
	for(int i=0;i<m;i++)
	{
		char x='a'+rand()%26;
		out<<x;
	}
	out<<'\n';
	int k=rand()%5+1;
	out<<k;
	out.close();
	return 0;
}

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、KMP算法的实现 KMP算法,全称为Knuth-Morris-Pratt算法,是一种用来解决模式串在文本串是否出现过的问题字符串匹配算法,KMP算法的核心是构造前缀表,通过前缀表来进行匹配,时间复杂度为O(m+n),其中m为模式串长度,n为文本串长度。 以下是KMP算法的C++实现: ```cpp #include <iostream> #include <cstring> using namespace std; void getNext(string pattern, int* next) { int j = 0; next[0] = 0; for (int i = 1; i < pattern.size(); i++) { while (j > 0 && pattern[i] != pattern[j]) { j = next[j - 1]; } if (pattern[i] == pattern[j]) { j++; } next[i] = j; } } int kmp(string text, string pattern) { int* next = new int[pattern.size()]; getNext(pattern, next); int j = 0; for (int i = 0; i < text.size(); i++) { while (j > 0 && text[i] != pattern[j]) { j = next[j - 1]; } if (text[i] == pattern[j]) { j++; } if (j == pattern.size()) { return i - j + 1; } } delete[] next; return -1; } int main() { string text = "hello world"; string pattern = "world"; int pos = kmp(text, pattern); if (pos != -1) { cout << "pattern found at position " << pos << endl; } else { cout << "pattern not found" << endl; } return 0; } ``` 2、利用KMP算法实现删除主串中所有包含子串的字符 思路:对于主串中的每个位置,判断以该位置为起点的子串是否包含子串,如果包含,则将该位置后的字符向前移动子串长度的距离。 以下是实现代码: ```cpp #include <iostream> #include <cstring> using namespace std; void getNext(string pattern, int* next) { int j = 0; next[0] = 0; for (int i = 1; i < pattern.size(); i++) { while (j > 0 && pattern[i] != pattern[j]) { j = next[j - 1]; } if (pattern[i] == pattern[j]) { j++; } next[i] = j; } } void removeSubstr(string& text, string pattern) { int* next = new int[pattern.size()]; getNext(pattern, next); int j = 0; for (int i = 0; i < text.size(); i++) { while (j > 0 && text[i] != pattern[j]) { j = next[j - 1]; } if (text[i] == pattern[j]) { j++; } if (j == pattern.size()) { // 删除子串 text.erase(i - j + 1, j); i -= j; // 回退i的位置 j = 0; // 重置j的值 } } delete[] next; } int main() { string text = "hello world"; string pattern = "lo"; removeSubstr(text, pattern); cout << text << endl; // 输出"h wrd" return 0; } ``` 以上就是模式匹配算法的实现以及利用模式匹配算法实现删除主串中所有包含子串的字符的代码实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值