C#,最长公共扩展(LCE,Longest Common Extention)的算法与源代码

一、最长公共扩展(LCE)问题

考虑一个字符串s,并为每对(L,R)计算从L和R开始的s的最长子字符串。
在LCE中,在每个查询中,我们必须回答从索引L和R开始的最长公共前缀的长度。

例子:

字符串:abbababba

查询:LCE(1,2)、LCE(1,6)和LCE(0,5)

求从索引(1,2)、(1,6)和(0,5)开始的最长公共前缀的长度。

突出显示的字符串“绿色”是从相应查询的索引-L和R开始的最长公共前缀。

我们必须找到从索引-(1,2),(1,6)和(0,5)开始的最长公共前缀的长度。

二、LCE的算法(朴素方法)

1、对于表格-LCE(L,R)中的每个LCE查询,请执行以下操作:

(1)将LCE“长度”初始化为0

(2)开始逐个字符比较从索引-L和R开始的前缀。

(3)如果字符匹配,那么这个字符在我们最长的公共扩展名中。所以增加“长度”(length++)。

(4)否则,如果字符不匹配,则返回此“长度”。

2、返回的“长度”将是所需的LCE(L,R)。

三、源程序

1、原始(Native)算法 

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{public class LCE_Query{/// <summary>/// 开始位置(下标)/// </summary>public int Left { get; set; } = 0;/// <summary>/// 结束位置(下标)/// </summary>public int Right { get; set; } = 0;/// <summary>/// 构造函数/// </summary>/// <param name="left"></param>/// <param name="right"></param>public LCE_Query(int left, int right){this.Left = left;this.Right = right;}}public static partial class LCE_Computation{public static int LCE(string str, int n, int left, int right){int length = 0;while ((right + length) < n && str[left + length] == str[right + length]){length++;}return (length);}public static List<string> LCEQueries(string str, int n, LCE_Query[] q, int m){List<string> vs = new List<string>();for (int i = 0; i < m; i++){int left = q[i].Left;int right = q[i].Right;vs.Add("LCE (" + left + ", " + right + ") = " + LCE(str, n, left, right));}return vs;}}
}

2、RMQ(Range Minimum Query)算法

RMQ(Range Minimum Query)算法,也称为 DMA(Direct Minimum Algorithm)算法。

其中使用凯撒(Kasai)算法从后缀数组中找到 LCP 数组。

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{public class Suffix : IComparable{/// <summary>/// original index/// </summary>public int index { get; set; } = 0;/// <summary>/// ranks and next rank pair/// </summary>public int[] rank = new int[2];public int CompareTo(object obj){Suffix b = obj as Suffix;if (this.rank[0] == b.rank[0] && this.rank[1] == b.rank[1]) return 1;return -1;//return ((this.rank[0] == b.rank[0]) ?//			(this.rank[1] < b.rank[1]) ://			(this.rank[0] < b.rank[0])) ? 1 : -1;}}/// <summary>/// 最长公共扩展/// Find the length of longest common extension/// using Direct Minimum Algorithm/// </summary>public class LCE_Direct_Minimum_Algorithm{private List<int> Build_Suffix_Array(string txt, int n){Suffix[] suffixes = new Suffix[n];for (int i = 0; i < n; i++){suffixes[i].index = i;suffixes[i].rank[0] = txt[i] - 'a';suffixes[i].rank[1] = ((i + 1) < n) ? (txt[i + 1] - 'a') : -1;}Array.Sort(suffixes);int[] ind = new int[n];for (int k = 4; k < 2 * n; k = k * 2){int rank = 0;int prev_rank = suffixes[0].rank[0];suffixes[0].rank[0] = rank;ind[suffixes[0].index] = 0;for (int i = 1; i < n; i++){if (suffixes[i].rank[0] == prev_rank && suffixes[i].rank[1] == suffixes[i - 1].rank[1]){prev_rank = suffixes[i].rank[0];suffixes[i].rank[0] = rank;}else{prev_rank = suffixes[i].rank[0];suffixes[i].rank[0] = ++rank;}ind[suffixes[i].index] = i;}for (int i = 0; i < n; i++){int nextindex = suffixes[i].index + k / 2;suffixes[i].rank[1] = (nextindex < n) ? suffixes[ind[nextindex]].rank[0] : -1;}Array.Sort(suffixes);}List<int> suffixArr = new List<int>();for (int i = 0; i < n; i++){suffixArr.Add(suffixes[i].index);}return suffixArr;}private List<int> Kasai(string txt, List<int> suffixArr, ref List<int> invSuff){int n = suffixArr.Count;List<int> lcp = new List<int>(n);for (int i = 0; i < n; i++){invSuff[suffixArr[i]] = i;}int k = 0;for (int i = 0; i < n; i++){if (invSuff[i] == n - 1){k = 0;continue;}int j = suffixArr[invSuff[i] + 1];while (i + k < n && j + k < n && txt[i + k] == txt[j + k]){k++;}lcp[invSuff[i]] = k;if (k > 0){k--;}}return lcp;}private int LCE(List<int> lcp, List<int> invSuff, int n, int L, int R){if (L == R){return (n - L);}int low = Math.Min(invSuff[L], invSuff[R]);int high = Math.Max(invSuff[L], invSuff[R]);int length = lcp[low];for (int i = low + 1; i < high; i++){if (lcp[i] < length){length = lcp[i];}}return (length);}public List<string> LCEQueries(string str, int n, LCE_Query[] q, int m){List<int> suffixArr = Build_Suffix_Array(str, str.Length);List<int> invSuff = new List<int>(n);List<int> lcp = Kasai(str, suffixArr, ref invSuff);List<string> result = new List<string>();for (int i = 0; i < m; i++){int L = q[i].Left;int R = q[i].Right;result.Add(String.Format("LCE ({0}, {1}) = {2}", L, R, LCE(lcp, invSuff, n, L, R)));}return result;}}
}

——————————————————————————

POWER BY  TRUFFER.CN

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/469060.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习、深度学习、强化学习、迁移学习的关联与区别

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本文主要了解并初步探究机器学习、深度学习、强化学习、迁移学习的关系与区别&#xff0c;通过清晰直观的关系图展现出四种“学习”之间的关系。虽然这四种“学习”方法在理论和应用上存在着一定的区别&#xff0c;但它们之间也…

什么是 Flet?

什么是 Flet&#xff1f; Flet 是一个框架&#xff0c;允许使用您喜欢的语言构建交互式多用户 Web、桌面和移动应用程序&#xff0c;而无需前端开发经验。 您可以使用基于 Google 的 Flutter 的 Flet 控件为程序构建 UI。Flet 不只是“包装”Flutter 小部件&#xff0c;而是…

51单片机编程基础(C语言):电子时钟(LED1602作为显示)

题目要求&#xff1a; 审题时这个题是用数码管来显示的&#xff0c;数码管显示时钟我完成了一个&#xff0c;只是要求跟他不一样&#xff0c;所以这次想用LCD1602来显示&#xff0c;所以我先用LCD1602完成&#xff0c;再用数码管完成&#xff08;其实也只要在我之前的项目基础…

《数电》理论笔记-第3章-常用组合逻辑电路及MSI组合电路模块的应用

一&#xff0c;编码器和译码器 1&#xff0c;编码器 编码:用由0和1组成的代码表示不同的事物。 编码器:实现编码功能的电路&#xff0c; 常见编码器:普通编码器、优先编码器、二进制编码器二-十进制编码器等等 1.1 三位二进制普通编码器和三位二进制优先编码器 1分58秒开始 …

洛谷_P1923 【深基9.例4】求第 k 小的数_python写法

哪位大佬可以出一下这个的题解&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;话说蓝桥杯可以用numpy库吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#xff1f; 这道题有一个很简单的思路就是排序完成之后再访问。 but有很大的问题&…

近十年金融资产收益率

通过掌握大类资产的历年收益率数据&#xff0c;做基于数据的投资&#xff0c;提高胜率和收益率。 下面是同花顺梳理的2014至2023大类金融资产收益率&#xff1a; 基于这个数据&#xff0c;我们再统计两项指标&#xff1a; 1. 每种资产在近十年的投资胜率&#xff08;收益率为…

哈希表 ?

哈希表 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释…

每日一练——月落乌啼算钱

题目&#xff1a; 举例&#xff1a; 输入&#xff1a;6&#xff0c;输出&#xff1a;8.00 最开始看到这道题还有点蒙&#xff0c;但是看到他的公式想起了斐波那契数列 1,1,2,3,5,8...... 由前两个数相加得到第三个数&#xff0c;为An2An1An。 可以得出这个题目中所给的通项就…

Spark编程实验六:Spark机器学习库MLlib编程

目录 一、目的与要求 二、实验内容 三、实验步骤 1、数据导入 2、进行主成分分析&#xff08;PCA&#xff09; 3、训练分类模型并预测居民收入 4、超参数调优 四、结果分析与实验体会 一、目的与要求 1、通过实验掌握基本的MLLib编程方法&#xff1b; 2、掌握用MLLib…

《UE5_C++多人TPS完整教程》学习笔记3 ——《P4 测试多人游戏(Testing Mutiplayer)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P4 测试多人游戏&#xff08;Testing Mutiplayer&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff08;也是译…

Java入门高频考查基础知识9(银盛15问万字参考答案)

JAVA刷题专栏&#xff1a;http://t.csdnimg.cn/9qscL 目录 一、Springcloud的工作原理 三、注册中心心跳是几秒 四、消费者是如何发现服务提供者的 五、多个消费者调⽤用同⼀接口&#xff0c;eruka默认的分配⽅式是什么 六、springboot常用注解&#xff0c;及其实现 七、…

【Java】零基础蓝桥杯算法学习——线性动态规划(一维dp)

线性dp——一维动态规划 1、考虑最后一步可以由哪些状态得到&#xff0c;推出转移方程 2、考虑当前状态与哪些参数有关系&#xff0c;定义几维数组来表示当前状态 3、计算时间复杂度&#xff0c;判断是否需要进行优化。 一维动态规划例题&#xff1a;最大上升子序列问题 Java参…