用graphviz画PAM
改编自“用graphviz画SAM”,作者yy1695651。
方法一:一键百度云链接:点我,提取码tvc4。
方法二:阅读以下内容:
第一步:安装 GraphViz,并配置环境变量。
洛谷日报上有安装教程。
第二步:生成 DOT 文件。
复制以下源代码:
#include <bits/stdc++.h>
using namespace std;
inline void read(register int &x){
x = 0; register int f = 1;
register char ch = getchar();
while (!(ch >= '0' && ch <= '9')){if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();}
x *= f;
}
const int MN = 5e6 + 10;
int len;
bool endpos[MN];
string stot = "\\n";
char s[MN];
struct PAM{
int s[MN], ch[MN][26], fail[MN], len[MN], last, tot, n;
PAM(){
memset(fail, -1, sizeof fail);
fail[0] = fail[1] = 1;
len[0] = 0; len[1] = -1;
tot = 1; last = 0;
s[0] = -1;
n = 0;
}
inline void Insert1(register int c){
s[++n] = c;
while (c != s[n - len[last] - 1]) last = fail[last];
if (!ch[last][c]) {
len[++tot] = len[last] + 2;
int k = fail[last];
while (c != s[n - len[k] - 1]) k = fail[k];
fail[tot] = ch[k][c];
ch[last][c] = tot;
}
last = ch[last][c];
}
inline void Print(){
printf("digraph test{\n");
printf(" node[shape=\"circle\"];\n");
printf(" rankdir=UD;\n");
printf(" subgraph cluster_sub1{\n");
printf(" 0");
for (register int i = 2; i <= tot; i++){
if (len[i] % 2 == 0) printf(",%d", i);
} printf(";\n");
for (register int ll = 0; ll <= tot; ll += 2){
int co = 0;
for (register int i = 2; i <= tot; i++)
if (len[i] == ll) ++co;
if (!co) continue;
printf(" {rank=same");
for (register int i = 0, f = 1; i <= tot; i++)
if (len[i] == ll) printf("%c%d", f ? ';' : ' ', i), f = 0;
printf("}\n");
}
printf(" }\n");
printf(" subgraph cluster_sub2{\n");
printf(" 1");
for (register int i = 2; i <= tot; i++){
if (len[i] % 2 == 0) printf(",%d", i);
} printf(";\n");
for (register int ll = -1; ll <= tot; ll += 2){
int co = 0;
for (register int i = 2; i <= tot; i++)
if (len[i] == ll) ++co;
if (!co) continue;
printf(" {rank=same");
for (register int i = 0, f = 1; i <= tot; i++)
if (len[i] == ll) printf("%c%d", f ? ';' : ' ', i), f = 0;
printf("}\n");
}
printf(" }\n");
for (register int i = 0; i <= tot; i++)
for (register int c = 0; c < 26; c++) if (ch[i][c])
printf(" %d:s->%d:n[color=blue,label=\"%c\";];\n", i, ch[i][c], c + 'a');
for (register int i = 0; i <= tot; i++)
printf(" %d->%d[color=green,style=dashed];\n", i, fail[i]);
register bool f = false;
printf(" ");
for (register int i = 0; i <= tot; i++) if (endpos[i]){
if (!f) {printf("%d", i); f = true;}
else printf(",%d", i);
}
printf("[style=\"filled\",fillcolor=\"chartreuse\"];\n");
printf(" ");
printf("\"Palindrome Automaton: \\n"); cout << stot;
printf("\"");
printf("[shape=plaintext];\n");
printf("}");
}
}pam;
int main(){
freopen("test.dot", "w", stdout);
scanf("%s", s + 1);
len = strlen(s + 1);
stot = s + 1;
for (register int i = 1; i <= len; i++) pam.Insert1(s[i] - 'a');
endpos[pam.last] = true;
pam.Print();
return 0;
}
编译运行源代码"PAMViz.cpp"/"PAMViz.exe"。
输入原串,只能包含英文小写字母。
生成 "test.dot" 文件。
第三步:命令行键入命令。
1、先进入你生成test.dot文件的主目录下。
2、用cd进入子目录
3、运行dot test.dot -T png -o test.png
第四步:打开生成的图片
可以看到新鲜的 PAM 可视化图片啦!
效果图展示