用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; ...
随机推荐
- setTimeout改变this指向(****************************************)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 【音乐App】—— Vue-music 项目学习笔记:歌曲列表组件开发
前言:以下内容均为学习慕课网高级实战课程的实践爬坑笔记. 项目github地址:https://github.com/66Web/ljq_vue_music,欢迎Star. 当前歌曲播放列表 添加歌曲 ...
- 字符集研究之多字节字符集和unicode字符集
作者:朱金灿 来源:http://blog.csdn.net/clever101 本文简介计算机中两大字符集:多字节字符集和unicode字符集的出现及关系. 首先我们须要明确的是计算机是怎样找到字符 ...
- mongodb分片片键的选择(持续更新中)
首先要了解项目的情况,检查使用情况 对集合进行分片时,要选择一个或者两个字段拆分数据,这个键叫做片键 一旦拥有对个分片,在修改片键几乎是不肯能的事情,因此选择合适的片键是非常重要的. 对集合分片之前要 ...
- 分层架构web容器的配置安全
转自:http://hi.baidu.com/shineo__o/item/7520d54c24d234c71081da82 /ps:本以为这是一个偶然配置失误造成的问题,但最近几天无聊时测试发现,有 ...
- centos下lvs配置
一.lvs-nat模式 网络配置: lvs-server eth0 :host-only adapter 192.168.56.101 lvs-server eth1 :Internal 192.16 ...
- UNP学习笔记(第二十五章 信号驱动式I/O)
信号驱动式I/O是指进程预先告知内核,使得当某个描述符发生某事时,内核使用信号通知相关进程. 套接字的信号驱动式I/O 针对一个套接字使用信号驱动式I/O(SIGIO)要求进程执行以下3个步骤: 1. ...
- js函数的Json写法
https://zhidao.baidu.com/question/83401454.html
- DataTable去除空行
protected void removeEmpty(DataTable dt) { List<DataRow> removelist = new List<DataRow>( ...
- java和erlang之间的DES加解密
app登录,登录的密码要用DES加密,服务器是用erlang,客户端要同时支持多平台(Android.iOS).首先,Java端的DES加密的实现方式, 少说废话了,直接上代码,如下: public ...