用c++后缀自动机实现最大公共字符串算法,并封装成Python库
后缀自动机的C++代码转自https://e-maxx.ru/algo/suffix_automata,其余封装为自写。
在C++文件同级目录建立setup.py文件,代码如下:
# !/usr/bin/env python
from distutils.core import setup, Extension
mod = "sam"
setup(name=mod, ext_modules=[Extension(mod, sources=['sam_lcs.cpp'])])
封装完后缀自动机的源码后,命令行编译、安装、卸载,安装后即可在Python里import调用:
python setup.py build
python setup.py install
python setup.py uninstall
包装模块的C++函数编写如下:
#include <map>
#include <string>
#include <Python.h> using namespace std; struct state
{
int len, link;
map<char, int> next;
}; const int MAXLEN = ;
state st[MAXLEN * ];
int sz, last; void sa_init()
{
sz = last = ;
st[].len = ;
st[].link = -;
++sz;
// 清除状态:
for (int i = ; i < MAXLEN * ; ++i)
st[i].next.clear();
}; void sa_extend(char c)
{
int cur = sz++;
st[cur].len = st[last].len + ;
int p;
for (p = last; p != - && !st[p].next.count(c); p = st[p].link)
st[p].next[c] = cur;
if (p == -)
st[cur].link = ;
else
{
int q = st[p].next[c];
if (st[p].len + == st[q].len)
st[cur].link = q;
else
{
int clone = sz++;
st[clone].len = st[p].len + ;
st[clone].next = st[q].next;
st[clone].link = st[q].link;
for (; p != - && st[p].next[c] == q; p = st[p].link)
st[p].next[c] = clone;
st[q].link = st[cur].link = clone;
}
}
last = cur;
}; string lcs(string s, string t)
{
sa_init();
for (int i = ; i < (int)s.length(); ++i)
sa_extend(s[i]); int v = , l = ,
best = , bestpos = ;
for (int i = ; i < (int)t.length(); ++i)
{
while (v && !st[v].next.count(t[i]))
{
v = st[v].link;
l = st[v].len;
}
if (st[v].next.count(t[i]))
{
v = st[v].next[t[i]];
++l;
}
if (l > best)
best = l, bestpos = i;
}
return t.substr(bestpos - best + , best);
}; static PyObject *sam_lcs(PyObject *self, PyObject *args)
{
char *stmp, *ttmp;
string s, t;
if (!PyArg_ParseTuple(args, "ss", &stmp, &ttmp))
return NULL;
s = stmp;
t = ttmp;
return PyUnicode_FromString(lcs(s, t).c_str());
}; static PyMethodDef sam_lcs_Methods[] = {
{"lcs", sam_lcs, METH_VARARGS,
"Get a longest common string of two strings with SAM"},
{NULL, NULL, , NULL}}; static struct PyModuleDef sam = {
PyModuleDef_HEAD_INIT,
"sam",
"SAM",
-,
sam_lcs_Methods}; PyMODINIT_FUNC
PyInit_sam(void)
{
return PyModule_Create(&sam);
};
编译安装完成后,就可以在Python里调用了
用c++后缀自动机实现最大公共字符串算法,并封装成Python库的更多相关文章
- 后缀自动机----一种将字符串变成DAG的方法
后缀自动机 (suffix automaton, SAM) 是一个能解决许多字符串相关问题的有力的数据结构.(否则我们也不会用它) 举几个例子,以下的字符串问题都可以在线性时间内通过 SAM 解决 1 ...
- SPOJ LCS 后缀自动机找最大公共子串
这里用第一个字符串构建完成后缀自动机以后 不断用第二个字符串从左往右沿着后缀自动机往前走,如能找到,那么当前匹配配数加1 如果找不到,那么就不断沿着后缀树不断往前找到所能匹配到当前字符的最大长度,然后 ...
- [SPOJ1811]Longest Common Substring 后缀自动机 最长公共子串
题目链接:http://www.spoj.com/problems/LCS/ 题意如题目,求两个串的最大公共子串LCS. 首先对其中一个字符串A建立SAM,然后用另一个字符串B在上面跑. 用一个变量L ...
- 一文读懂后缀自动机 Suffix_Automata
原论文(俄文)地址:suffix_automata 原翻译(中文)地址:后缀自动机详解(DZYO的博客) Upd:强推浅显易懂(?)的SAM讲解 后缀自动机 后缀自动机(单词的有向无环图)--是一种强 ...
- 牛客多校第四场 I string 后缀自动机/回文自动机
这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅! 题意: 求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个. 题解: 要注意的是,一般字符串题中的“ ...
- SPOJ 1811. Longest Common Substring (LCS,两个字符串的最长公共子串, 后缀自动机SAM)
1811. Longest Common Substring Problem code: LCS A string is finite sequence of characters over a no ...
- SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)
题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...
- BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
题目描述 在虐各种最长公共子串.子序列的题虐的不耐烦了之后,你决定反其道而行之. 一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是. 一个串的“子序列”指的是它的可以 ...
- 字符串数据结构模板/题单(后缀数组,后缀自动机,LCP,后缀平衡树,回文自动机)
模板 后缀数组 #include<bits/stdc++.h> #define R register int using namespace std; const int N=1e6+9; ...
随机推荐
- html5扫面二维码逻辑
写在前面 项目中有这样的需求,在android端嵌入的html5应用中,需要扫描二维码,而一般的浏览器是不允许你调用摄像头的.最后时限方式是由app的webview进行扫描,将扫描结果返回,也就是js ...
- weblogic多池与oracle集群RAC
http://www.techpaste.com/2013/04/soa-infra-start-fails-weblogic-common-resourceexception-good-connec ...
- 常用 linux操作
查看libreoffice进程 ps -ef | grep libreoffice
- 手把手教你画AndroidK线分时图及指标
先废话一下:来到公司之前.项目是由外包公司做的,面试初,没有接触过分时图k线这块,认为好难,我能搞定不.可是一段时间之后,发现之前做的那是一片稀烂,可是这货是主功能啊.迟早的自己操刀,痛下决心,开搞, ...
- 【Python】Python中in与not in
在python中,要判断特定的值是否存在列表中,可使用关键字in,判断特定的值不存在列表中,可使用关键字not in letters = ['A','B','C','D','E','F','G'] i ...
- Django--网页管理实例解析
此篇为代码流程的注释以及自己写的小项目的思路: 首先是项目的路由配置: urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^yemia ...
- 深入浅出Attribute(二)
上篇里,我们把Attribute“粘”在类的成员方法上show了一把,让Attribute跟大家混了个脸儿熟.中篇里,我们将探讨“究竟什么是Attribute”和“如何创建及使用Attribute”这 ...
- PHP中__get()和__set()的用法实例详解
php面向对象_get(),_set()的用法 一般来说,总是把类的属性定义为private,这更符合现实的逻辑.但是,对属性的读取和赋值操作是非常频繁的,因此在PHP5中,预定义了两个函数“__ge ...
- Docker入门系列5:常见问题小结
重启容器 再次运行容器: docker start container_id 然后 docker attach container_id 就可以继续下命令了. [编辑]命名 --name [编辑]端口 ...
- 多媒体开发之---如何确定slice_header slice_type 的位置
引用网友的问答:我找到0x000001 NAL的开头了,请问如何确定slice head的位置,继而得出slice_type呢?Nal unit后紧跟的就是slice head吗?标准里的循环让人看得 ...