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
C#,最长公共扩展(LCE,Longest Common Extention)的算法与源代码相关推荐
- C#LeetCode刷题之#14-最长公共前缀(Longest Common Prefix)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3921 访问. 编写一个函数来查找字符串数组中的最长公共前缀. 如 ...
- 最长公共子串LCS (Longest Common Subsequence) 算法
三个方法都有所借鉴,但代码部分是自己试着写出来的,虽然最后的运行结果都是正确的,但此过程中难免会有考虑不周全的地方,如发现代码某些地方有误,欢迎指正.同时有新的想法,也可以提出! 采用顺序结构存储串, ...
- [LeetCode]最长公共前缀(Longest Common Prefix)
题目描述 编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow ...
- Leetcode 14.最长公共前缀(Longest Common Prefix)
Leetcode 14.最长公共前缀 1 题目描述(Leetcode题目链接) 编写一个函数来查找字符串数组中的最长公共前缀.如果不存在公共前缀,返回空字符串 "". 输入: ...
- 最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr...
问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y=& ...
- 动态规划—最长公共子序列问题 HDU-1159 Common Subsequence
动态规划-最长公共子序列问题 Common Subsequence [ HDU - 1159 ] A subsequence of a given sequence is the given sequ ...
- 两个字符串的最长公共子序列长度_程序员编程算法,解决文本相似度问题的最长公共子序列算法!...
在前面我讲解了如何通过最长公共子串来求解两个文本的相似度问题,但它有一定缺陷,举个例子,看下面的两个字符串 我爱吃小青菜和各种鲜水果. 我很爱吃青菜与各样水果. 上面两个字符串,如果通过计算子串来求相 ...
- 动态规划算法解最长公共子序列LCS问题
动态规划算法解LCS问题 作者 July 二零一零年十二月三十一日 本文参考:微软面试100题系列V0.1版第19.56题.算法导论.维基百科. 第一部分.什么是动态规划算法 ok,咱们先来了解下什么 ...
- 编辑距离:最长公共子序列-LCS问题
一.基本概念 LCS是最长公共子序列(Longest common subsequence problem)的缩写.LCS问题是在一组序列(通常只有两个序列)中找到所有序列共有的最长子序列的问题.它与 ...
最新文章
- 转变矛头,号称攻破BCH网络的Bitpico或与BCE决裂
- EL表达式和JSTL
- VMX虚拟机环境下CentOS/Linux扩展磁盘空间,并且增加HOME目录的大小!
- CakePHP下使用paginator需要对多个字段排序的做法
- catia测量工具小尺子在哪_小区垃圾桶旁捡来旧茶几,老爸巧手改成沙发,邻居一个劲问哪买的...
- mysql connection_id 表锁的应用
- net 架构师-数据库-sql server-002-工具
- 传聊天宝团队解散 罗永浩已退出股东行列
- 权威指南之脚本化jquery
- java混淆工具zelix比较_常用的5款java混淆器
- 黑盒测试设计专题:正交试验
- excel交换两列笔记
- java中ArrayList小案例(快敲20遍++)
- c语言操作符的自我总结hhhhhhhhh
- springboot+shiro+nutz+beetl + mysql
- 【转】正则表达式 匹配中文,英文字母和数字及_的写法!同时控制长度
- Response.addHeader()和Response.setHeader()的区别,别再傻傻分不清;
- 什么是哲学,兼谈如何理解道德经
- 自动刷抖音极速版得红包金币(APP实现)
- 文件太大无法复制到U盘