Image Basics

Color Hue: pure color, presented by a circle Saturation: purity of color, how far it is from pure white, which is every color combined Brightness: subjective perception, how far it is from grey Luminance: objective, cd/m2 Contrast: Sharpness: Noise Image noise is random variation of brightness or color information in images, and is usually an aspect of electronic noise. Gaussian noise Salt-and-pepper noise Shot noise Quantization noise Film grain Anisotropic noise Periodic noise Photography Backlight The process of illuminating the subject from the back. The lighting instrument and the viewer face each other, with the subject in between, creating a glowing effect on the edges of subject, which helps to seperate the subject and the background. In photography, a back light (often the sun) that is about sixteen times more intense than the key light produces a silhouette. ...

2018年12月5日 · 2 分钟 · 770 字 · Dai Chao

简单的字符串练习1

初次尝试刷题,当然要刷简单的啦。 Root :: Competitive Programming 3: The New Lower Bound of Programming Contests (Steven & Felix Halim) :: String Processing :: String Matching :: Standard 455 - Periodic Strings **问题描述:**求一个字符串的最小周期,例如"123123123"的最小周期为3。从数据规模来看,穷举法完全可行,但还是要学习一下这位老哥对KMP的巧妙运用: ...

2018年11月13日 · 6 分钟 · 2756 字 · Dai Chao

LCP数组、后缀自动机、后缀树(?)

LCP数组 定义 有了后缀数组,也就有了每个后缀的大小顺序。 但现在我们有另一个奇怪的需求: 对于任意两个后缀,求它们的最长公共前缀(Longest Common Prefix, LCP)。 啊?为什么有这个需求?我也不知道,但大佬说很有用,那就求吧。 ...

2018年11月2日 · 6 分钟 · 2848 字 · Dai Chao

神奇的优化方式

Kickstart Round F 2018第一名Benq的参赛代码,光开头几行就把我吓得魂飞魄散。 #pragma GCC optimize ("O3") #pragma GCC target ("sse4") #include <bits/stdc++.h> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/assoc_container.hpp> #include <ext/rope> using namespace std; using namespace __gnu_pbds; using namespace __gnu_cxx; #define sz(x) (int)(x).size() template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag,tree_order_statistics_node_update>; void setIn(string s) { freopen(s.c_str(),"r",stdin); } void setOut(string s) { freopen(s.c_str(),"w",stdout); } void io(string s = "") { ios_base::sync_with_stdio(0); cin.tie(0); if (sz(s)) { setIn(s+".in"); setOut(s+".out"); } } int main() { io("A"); // ... } GCC Function Attributes #pragma GCC optimize ("O3") #pragma GCC target ("sse4") Common Function Attributes x86 Function Attributes 指定GCC做O3优化,支持SSE4指令。 ...

2018年11月2日 · 1 分钟 · 440 字 · Dai Chao

The KMP Algorithm

Not difficult to understand. I learned it from Coursera. Prefix Function A “Border” of a string, is a substring that both acts as a prefix and a suffix of that string The “Prefix Function” of a string records the length of the longest border of every prefix of that string Symbol s is a string s[:i] is a prefix of s made up by s[0], s[1], ..., s[i-1] L[i] is the length of the longest border of s[:i] In other words, L is the “Prefix Function” of s Conclusion L[i+1] <= L[i]+1, and the equality holds if and only if s[L] = s[i] The longest border of the longest border of a string, is the second longest border of that string. if some border of s[:i] has a length of len and s[len] = s[i], then there must be a border in s[:i+1] with a length of len+1 Method L[0] = 0 L[i+1] = len + 1, where len is the length of the longest border of s[:i] that satisfies s[len] = s[i] To find len, try every border of s[:i] from the longest to the shortest To find the next longest border, see Conclusion 2 If no border is found, simply compare s[0] with s[i] If s[0] = s[i], then L[i+1] = 1 Else, L[i+1] = 0 Implementation int *pf(string s) { int len=s.size(),b=0; int *p=new int[len]; p[0]=0; for(int i=1;i<len;i++) { while(b>0 && s[i]!=s[b]) b=p[b-1]; if(s[i]==s[b]) b++; p[i] = b; } return p; } KMP Symbol p is the pattern string, t is the text string L is the “Prefix Function” of p Conclusion If p matches t partially with a longest common prefix p[:i], then no matches will be found before p is shifted len(p) - L[i] positions rightwards. There are two “submatches” in this partial match, both of which are the longest border of p[:i] The left one acts as a prefix, while the right one acts as a postfix p is shifted rightwards, so does p[:i] No matches are possible before the left submatch arrives at the previous position of the right submatch The length of this “vacuum area” is len(p) - L[i] Method Make s = p + '$' + t, where ‘$’ is absent from both p and t Calculate the “Prefix Function” of s, marked as L A match is found at position i - 2 * len(p) when L[i] = len(p) Under such circumstances, the longest border of s[:i] happens to be p itself, as p is a prefix of s This border is also a substring of s Thanks to the ‘$’ sign, we can guarantee that this border never crosses the real “border” between p and t, so it is also a substring of t Thus the starting position of the match is i - (len(p) - 1) in s, and i - (len(p) - 1) - (len(p) + 1) in t Implementation int main() { string pattern, text, s; int *pf; while(cin >> pattern >> text && pattern != "") { if(pattern.size() > text.size()) { cout << "-1" << endl; continue; } s = pattern + "$" + text; pf = prefix_func(s); for(int i = pattern.size()+1; i < s.size(); i++) { if(pf[i] == pattern.size()) { cout << i - 2 * pattern.size() << " "; } } cout << endl; delete pf; } return 0; }

2018年10月29日 · 2 分钟 · 557 字 · Dai Chao

破解外星代码:详解后缀数组模板

朕听说,后缀数组只需寥寥二十行代码即可求出? 是,陛下。 快,快呈上来! 是,陛下。 int wa[MAXN], wb[MAXN], wv[MAXN], ws[MAXN]; inline bool cmp(int *r, int a, int b, int len) { return r[a]==r[b] && r[a+len]==r[b+len]; } void SA(char *r, int *sa, int n, int m) { int i, j, p, *x = wa, *y = wb, *t; for (i = 0; i < m; i++) ws[i] = 0; for (i = 0; i < n; i++) ws[x[i] = r[i]]++; for (i = 1; i < m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i; for (j = p = 1; p < n; j <<= 1, m = p) { for (p = 0, i = n - j; i < n; i++) y[p++] = i; for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i < m; i++) ws[i] = 0; for (i = 0; i < n; i++) ws[wv[i] = x[y[i]]]++; for (i = 1; i < m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; for (t=x,x=y,y=t, x[sa[0]]=0, p=i=1; i<n; i++) x[sa[i]] = cmp(y,sa[i-1],sa[i],j) ? p-1 : p++; } } 陛下……陛下!快请御医! 前言 鉴于我也是第一次接触后缀数组,理解程度还很低,再加上类似的博客早已烂大街,因此不求读者能看懂或学到什么东西了。你还可以向我留言提出指导意见,我会非常欢迎。 ...

2018年10月29日 · 9 分钟 · 4162 字 · Dai Chao

C++查漏补缺

我已经不怎么记得“程序设计实习”的内容了。 C与C++的(细微)区别 C++支持,但C不支持 面向对象 重载、模板、继承、虚函数、友元函数 语言层面上的异常处理 引用 输入输出流 new/delete/explicit/class等关键词 结构体中定义成员函数 结构体中定义静态变量 直接在结构体中初始化成员变量 C支持,但C++不支持 调用尚未声明的函数 将const的地址赋给non-const指针 将void*值直接赋给其他指针,malloc()返回的就是void* 不初始化const char *c = 333 其他 C认为func()=func(…),即func可以接受任意个数的参数。C++认为func()=func(void),即func不能接受参数。因此在C中使用func(void)会显得你更专业、更严谨 C认为字面字符常量是整数,C++则认为是字符。sizeof('a'),前者得到4,后者得到1 C的结构体类型必须带上struct前缀。struct T; T a;是不合法的C代码,但C++认为没问题 sizeof(1==1)的C值为4,C++值为1,因为C++支持bool类型 空结构体的sizeof值在C是0,在C++是1 引用和指针的区别 总地来说,引用不如指针灵活,但更安全。引用值必须 ...

2018年10月26日 · 7 分钟 · 3070 字 · Dai Chao

Crowbar源码剖析:语法

Introduction 上回书说到,Crowbar的词法分析器将具体的源码文件解析为一串抽象的符号,并伴随着一系列附属动作。接下来轮到Crowbar的语法分析器登场了——它是如何解读这串符号的?解读的同时又做了些什么事情呢?我们一起来看看。 本篇有非常多杂七杂八的代码,看的时候一定要把握住最大的共同点——语法和数据结构的高度一致。很多代码都是相似的,把握住设计思想才是最关键的。 ...

2018年10月8日 · 9 分钟 · 4508 字 · Dai Chao

Crowbar源码剖析:词法

Introduction 上回书说到,Crowbar用了Lex/Yacc这对经典工具来生成词法/语法分析器。它们具体的编写规则我不想细说,请参考这篇文章,但大致来讲,两者都是“一边匹配一边触发动作”。 本篇文章会集中讨论匹配触发了哪些动作,而不讲如何匹配、为什么匹配。 Crowbar-Lex 这部分讲述Lex如何对五花八门的字符作出不同反应,用<X>exp{action}表示“状态X下,与exp匹配时,执行action”。为了给Yacc传递符号的解析结果,双方约定了一种“通信方式”: ...

2018年10月7日 · 4 分钟 · 1665 字 · Dai Chao

Crowbar源码剖析:总体框架

Introduction Crowbar是《自制编程语言》一书中作者自己构思的无类型语言。本书一边向读者讲述编程语言的基本要素,一边讲解具体的实现方法,可作为编译技术的入门材料。此外,书中还有一门叫做Diksam的静态类型语言,等我学完了再来写。不🐦,真的。 ...

2018年10月6日 · 4 分钟 · 1696 字 · Dai Chao